Git, CI/CD & GitOpsLIX · RollbackTerraform
Terraform rollback via state and applied — terraform state list and the targeted apply
What you'll learn
- Inspect Terraform state with terraform state list to identify what Terraform owns
- Perform a rollback by reverting the configuration and applying a fresh reviewed plan, reserving terraform apply -target=<address> for exceptional error recovery
- Recognise the boundaries of state-driven rollback - resources deleted out-of-band cannot be undone
- Build the discipline of validating state after a rollback
Prerequisites
Verified against Git 2.55.x teaching target; 2.40+ minimum · GitHub Actions continuous service; Aug 2026 documentation baseline · Argo CD v3.5.x teaching target; v3.0+ minimum · Flux v2.9.x · Sigstore Cosign v3.1.x · SLSA v1.2 · OCI Distribution Specification v1.1 · Git LFS v3.7.1 · Kubernetes (cross-course target) 1.36.x
Terraform rollback is not a button. It is a state-driven apply. The state file is the inventory of what Terraform owns; the configuration is the declaration of what Terraform wants; the apply reconciles the two. A rollback is the act of pointing the configuration at a previous commit and letting Terraform reconcile. The mechanism is the same apply the team has been running all along; the rollback is a change in the commit the apply reads.
How state-driven rollback works
Terraform’s model is declarative. The configuration declares the desired state; the state file records the current state; the apply reconciles the two. A rollback does not change this model: it changes what the configuration declares.
flowchart LR
A["Commit HEAD"] --> C["Configuration"]
B["Commit HEAD~1"] --> C2["Configuration (previous)"]
C --> D["State file"]
D --> E["apply (HEAD)"]
C2 --> D
D --> F["apply (HEAD~1) = rollback"]
The rollback procedure:
- Identify the previous commit.
git logon the configuration repository; the post-mortem may name a specific SHA. - Inspect state:
terraform state listnames every resource Terraform still believes it owns. The list is the inventory for the rollback. - Revert the commit (
git revertor new commit that reverts the bad change), runterraform planagainst the current state, review the full diff, then apply. The apply reconciles the rolled-back configuration against the current state; the resources Terraform owns are brought back to the previous shape. - Validate.
terraform planafter the rollback should show no changes; drift between the rolled-back configuration and the actual cloud is the failure mode.
When the bad change touched a single resource, the revert
itself is already scoped: a git revert of the offending
commit changes only that resource’s configuration, so the
fresh plan touches only that resource. In exceptional
error-recovery situations - a partially failed apply that
must be unwound before a clean plan can run - Terraform
can scope an apply to one address:
terraform apply -target=$ADDRESS
The -target flag scopes the apply to a single resource
address (module.x.aws_security_group.y,
aws_instance.z, etc.). Terraform prints a warning every
time the flag is used, and the documentation reserves it
for error recovery: routine use is an anti-pattern,
because a targeted apply skips the rest of the dependency
graph and leaves state only partially reconciled.
terraform state list as the inventory
The first command in any rollback is the inventory:
terraform state list
The output is a list of resource addresses in the state.
A module is named by its path (module.network.aws_vpc.main);
a top-level resource by its address
(aws_security_group.api). The list is what Terraform can
roll back; everything else has been deleted, replaced, or
never tracked.
What the list tells the operator:
- A resource is missing from the list. It was removed
from the configuration and the removal was applied; the
rollback can re-declare it, but the cloud resource may
have been destroyed.
terraform importmay be needed. - A resource is in the list but not in the cloud. It was deleted out-of-band; the state is stale. The rollback cannot restore what the cloud no longer holds without a recreation.
- A resource is in the list and in the cloud but drifted. It was modified by hand; the rollback will reconcile it back to the configuration’s declaration, potentially destroying manual changes.
The list is not optional. A rollback that proceeds without inspecting it is gambling that state matches reality.
What state-driven rollback can and cannot do
The boundary state-driven rollback crosses is the cloud resource Terraform owns. What it can do:
- Revert a resource’s configuration to the shape declared in the previous commit.
- Recreate a resource that was deleted from the configuration but is still in state and still in the cloud (or importable from the cloud).
- Destroy a resource that was added in a bad commit and apply against the reverted configuration.
What it cannot do:
- Restore a resource that was deleted out-of-band (by
hand, by another tool, by cloud console). State says
Terraform owns it; the cloud does not. The rollback
cannot conjure a deleted resource back without
terraform importand a recreation. - Roll back a non-Terraform change. A resource created by the cloud console, by an Ansible run, by a kubectl apply is invisible to Terraform. The rollback leaves it alone.
- Roll back data without a backup. A database that Terraform provisioned but a separate process populated is restored to the schema, not to the data. The rollback is structural, not data-level.
- Roll back a multi-resource change atomically. A
Terraform apply is the unit of atomicity. A
-targetapply on resource A followed by another-targetapply on resource B is two applies, not one. The cloud sees intermediate states.
When to use targeted apply
A targeted apply (terraform apply -target=$ADDRESS) is
an error-recovery instrument, not a rollback path.
Terraform warns on every use; the exceptional cases:
- A partially failed apply blocks a clean plan. An apply died mid-run and left one resource in a state that makes every full plan error out; the targeted apply unwinds that one resource so the full reviewed plan can run again.
- A single resource must be repaired before the full reconciliation. A broken dependency prevents the full apply from converging; repairing the one address first unblocks the rest.
- A dependency deadlock is being unwound step by step. Resource B depends on Resource A; the full apply fails because A still references the new shape. Targeted applies in dependency order unblock each step - followed by a full plan to reconcile.
The risks:
- Drift introduced by the targeted apply on the rest of the state. A targeted apply changes one resource; the next full plan will show the change correctly, but intermediate states may have inconsistent references.
- Hidden dependencies. A resource that does not declare a dependency on the targeted resource may nonetheless break when the target is rolled back. The targeted apply does not enforce the full dependency graph.
Production discipline
- Run
terraform planbefore every rollback. Read the diff. Confirm the plan is the expected rollback and not a surprise. - Inspect state with
terraform state listbefore applying. Confirm what Terraform still owns; identify the gap between state and reality. - Prefer the full revert-and-apply over a targeted
apply. Terraform warns on every
-targetuse; the flag is for exceptional error recovery, and the full reviewed plan is the default and the safer pattern. - Treat state drift as a rollback blocker, not an
inconvenience. A
terraform refresh(orplan -refresh-only) before the rollback reconciles state to reality; the rollback then proceeds against an accurate state. - Validate after the rollback.
terraform planshould show no changes; a non-empty diff means the rollback is incomplete or the configuration has drifted further.
Cross-course references
- Terraform for Production Sysadmins - Part XII (State) covers state backends, locking, and drift detection.
- This course, Part L (Terraform CI) covers the plan-as-artifact discipline that produces auditable rollback targets.
- This course, Part XXVII (Repository layouts) covers the Terraform repository structure that the rollback reverts.
Quiz
Knowledge check · 4 questions
Q1. A team needs to roll back a Terraform change that affected a single security group, without disturbing the rest of the infrastructure. What is the correct rollback procedure?
Q2. If a resource has been deleted from the cloud by an out-of-band process (a console action, a separate script), Terraform can still roll it back via `terraform apply` against the previous commit because the state file still records Terraform as the owner.
Q3. What is the role of `terraform state list` in a rollback procedure, and what does the operator learn from it?
Q4. Diagnose why a Terraform rollback reported success but the cloud resource did not change, and identify the production discipline that prevents recurrence.
A team reverts a Terraform commit that opened a security group rule, runs `terraform apply`, and observes 'no changes'. The team believes the rollback succeeded. An hour later, a security audit finds the security group rule is still open. Investigation reveals that a separate on-call engineer had manually edited the security group in the cloud console two weeks earlier to add a temporary rule for debugging. The state file was not refreshed; the apply compared configuration against stale state and produced a no-op.
Passing score: 75%. Answers are checked in this browser.