Automation and Infrastructure as Code
Declare, don't click
Declarative IaC describes the desired end state and lets the tool compute the diff; imperative scripts describe steps and are rarely idempotent. Idempotency is the core property: running the same definition twice must produce the same result, not two of everything. Anything created by hand in a console is invisible to the next apply and becomes drift, which is why manual hotfixes must be back-ported into code immediately.
State, modules, and pipelines
State maps declared resources to real ones; losing or sharing it badly is the classic failure. Use a remote backend with locking so two applies cannot race, keep state out of version control, and treat state as sensitive because it can contain secrets and plaintext attributes. Package resources into versioned modules so environments differ only by variables. Policy as code can block disallowed resource types before apply.
GitOps
With GitOps, the repository is the source of truth and a controller continuously reconciles cluster or environment state toward it. This gives an audit trail and automatic drift correction, but only if every change goes through a reviewed merge and the pipeline identity is least-privileged.
Traps candidates fall for
- Assuming a saved plan stays valid; state may have changed since it was generated.
- Sharing one state file or environment across teams, so one apply destroys another's work.
- Putting secrets in variable files or state, then relying on repository permissions.
- Running IaC once at bootstrap and never again, so it no longer matches reality.
- Granting the pipeline owner-level rights because scoping takes longer.
Rule of thumb
If a resource is not in code, it does not exist for the next change. Every manual fix ends with a commit.
Worked example
An engineer changes a security group in the console during an incident. The next pipeline run shows a plan that would revert it. Correct response: encode the emergency change in the repository, merge it, and let the apply converge; then add a policy check or drift alert so the gap is caught in minutes rather than at the next unrelated deploy.