The object being reviewed
Imagine a fictional change to a funds-processing service. At 10:00 a team reviews a plan; at 10:15 another commit reaches the execution directory. The operational question is which proposal will run. In the workshop, terraform_data retains only values in temporary state. The plan contains approved-a, but the file changes to working-b before apply. Given the saved file, the CLI applies approved-a. It does not treat the new file as an additional approved change. Review must identify the artifact actually delivered for execution and the context that produced it.
A proposed change after execution
After saved-plan application, the script plans again with the file containing working-b. A pending update appears and detailed-exitcode returns 2. The earlier execution can be correct relative to its plan even though current configuration requests something else. Record approved intent separately from the latest intent. Do not automatically treat the second plan as a continuation of the first authorization. In a pipeline, the decision depends on the defined change process, affected resources and current conditions. The exercise retains the second plan without applying it so that this boundary remains observable.
Integrity does not establish freshness
A second case starts from existing state. The script saves old.plan, applies an intervening change and attempts old.plan. The plan hash remains identical. Nevertheless, the CLI rejects it with Saved plan is stale; the state serial advanced within the same lineage. In this experiment the rejected attempt leaves the state file unchanged. Investigate the intervening operation, confirm current intent and produce a new plan for review. Restoring old state merely to try to make the plan pass does not undo infrastructure effects and can hide correct bindings between configuration and objects.
The target has its own identity
The workshop creates two independent directories with the same initial configuration. Each receives local state with a different lineage. Copying a plan made in the first directory into the second causes rejection for different lineage; the second state remains intact. This observation shows that matching names and values do not establish state identity. At work, include backend, workspace, account, region and permissions when identifying the target. The exercise contacts no remote backend and does not establish that these controls exist in a pipeline. The environment decision requires its own evidence.
Authorization precedes the command
Passing a saved plan to apply is sufficient for the CLI to execute without interactive confirmation. This does not establish business, security or change-window approval. Those controls belong to the workflow delivering the artifact. In the experiment, adding -var to saved-plan apply is rejected before state creation: planning decisions are already in the file. If an input must change, generate and review another proposal. A useful approval record associates plan identity, configuration origin, target, owner, constraints and expected result according to the organization’s process.
Interpret the result and close the change
The script observes all three plan outcomes with detailed-exitcode: 0 for no changes, 2 for proposed changes and 1 for a configuration error. These codes require different automation paths. Code 2 should not trigger application without the required decision; code 1 is not equivalent to an empty plan. Even after obtaining 0, the workshop establishes only that its local model proposes no changes. Application health, functional reconciliation and support readiness require additional checks. In the handover, state explicitly which checks were performed and which remain outstanding.
# Run only in a new local terraform_data exercise directory.
terraform init -input=false
terraform plan -input=false -out=approved.plan
terraform show -no-color approved.plan
# Applying the saved file is treated as approval by the CLI.
terraform apply -input=false approved.plan
terraform plan -input=false -detailed-exitcode
# Interpret exit status: 0 no changes; 2 changes; 1 error.
The plan stores approved-a; the file changes to working-b. Saved-plan execution applies approved-a and the next plan proposes working-b.
Common pitfalls
Confusing the current commit with a saved plan; interpreting a hash as authorization; trying to bypass state rejection by restoring an old copy.
Related topics: Plan review and approval · State and operational recovery
File integrity and execution validity answer different questions. Establish both before the change.
Reference: Saved-plan execution and planning options · Terraform v1.16 concepts; official documentation consulted 2026-09-30; provider and backend capabilities must be confirmed