Terraform Plan Shows It Will Destroy Everything: The Prevention Checklist
⏱️ 2 min read
When terraform plan suddenly wants to destroy and recreate half your infrastructure, it is almost never a Terraform bug — it means Terraform no longer recognizes your existing resources as the same ones your code describes. Find which identity assumption broke, and the destroy plan disappears.
The five usual suspects
1. Renamed or moved resource blocks. A resource's identity is its address (aws_instance.web_app). Rename the block and Terraform sees destroy + create. The fix is moved blocks — declare the rename and plan becomes a no-op.
2. Count/for_each churn. Adding an item to the front of a count-based list shifts every index. Prefer for_each with stable keys (map keys, not list positions) for anything with real state.
3. State drift. Someone changed the console or an autoscaler tagged instances. terraform plan -refresh=false can tell you whether drift is the trigger; terraform import re-adopts manually-changed resources.
4. Provider upgrade. Major provider versions change attribute semantics (the AWS provider v4→v5 migration being the famous one). Pin your versions in the lock file and read the upgrade notes before terraform init -upgrade.
5. Workspace/env confusion. Planning the wrong workspace makes Terraform compare prod state against staging code. Echo terraform workspace show in your CI before every apply.
The habit that prevents all of it
Never apply from a laptop. Run plans in CI where the plan file is an artifact, applies require a reviewed approval, and -lock-timeout prevents concurrent runs. A state snapshot before apply (terraform state pull > backup.tfstate) turns any mistake into a restore instead of a rebuild. Testing risky migrations on throwaway infrastructure — an hourly cloud server costs cents — is cheaper than one bad apply on prod.