How would you make it structurally difficult for someone to accidentally run terraform destroy against a production state?
Short Answer
Layer several independent protections: prevent_destroy lifecycle blocks on genuinely critical resources (a hard Terraform-level block regardless of command), separate state files/backends per environment so there's no single command that can touch both staging and production, CI/CD-enforced approval gates specifically for any plan showing a destroy action, and restricted local apply/destroy credentials so production changes can only happen through the reviewed pipeline, not an individual's local machine — no single layer is foolproof, but together they make an accidental production destroy require several independent mistakes to actually happen, not just one.
Detailed Explanation
Relying on human carefulness alone as the only safeguard against terraform destroy is exactly the kind of single point of failure that eventually fails — the design goal is making an accidental destroy require multiple independent things to go wrong simultaneously, not just one lapse in attention.
lifecycle { prevent_destroy = true } on genuinely critical resources is a hard, Terraform-level block: setting this on a production database, a critical stateful resource, or similar means Terraform itself refuses to destroy that specific resource regardless of what command is run or what the plan says — this is the most direct, resource-specific protection, though it only protects the specific resources it's applied to, not the broader state.
Separate state files/backends per environment eliminates "wrong environment" as a possible mistake category entirely: if production and staging use genuinely separate state backends (different S3 buckets/paths, different workspaces with separate backend configuration, not just different variable values against the same state), there's no single Terraform command, run from a single directory/context, that could ever accidentally touch both — the blast radius of any command is structurally confined to whichever environment's state is currently configured.
CI/CD-enforced approval gates specifically for destroy-containing plans: a pipeline that requires explicit human approval before any apply proceeds, and specifically flags/highlights when a plan includes any destroy action (not just showing the full diff for someone to potentially skim past), adds a deliberate human checkpoint precisely at the moment of highest risk.
Restricting who/what has credentials capable of running apply/destroy against production reduces the pool of things that could make this mistake: if production changes can only happen through the CI/CD pipeline's own service account/role (not through any individual's personal local credentials), an individual's local terraform destroy command, even if run by mistake, simply lacks the permissions to actually affect production — this converts "a person made a mistake" into "a person made a mistake that structurally couldn't do damage."
Combine these layers deliberately rather than relying on any single one: prevent_destroy for the specific handful of truly irreplaceable resources, separate state/backends per environment as the structural foundation, pipeline-enforced approval specifically gating destroy-containing plans, and credential restriction ensuring production changes can only happen through that reviewed pipeline. None of these individually is bulletproof (a prevent_destroy block can itself be removed by someone with access to the code, for instance), but together they require several independent failures to align for an accidental production destroy to actually happen.
Interview Follow-Up Questions
- How would you handle a genuine, legitimate need to destroy a `prevent_destroy`-protected resource, given the protection is designed to be a hard block?
- What would you do if someone needs emergency local access to run Terraform directly against production during an incident, given the credential-restriction layer normally prevents this?
- How would you audit an existing set of Terraform configurations to find critical resources that currently lack `prevent_destroy` protection?
Key Takeaways
prevent_destroyis a hard, resource-specific Terraform-level block, but only protects the specific resources it's applied to.- Separate state files/backends per environment structurally eliminates "ran the right command against the wrong environment" as a possible mistake category.
- CI/CD approval gates specifically flagging destroy-containing plans add a deliberate human checkpoint at the highest-risk moment.
- Restricting production-apply credentials to only the CI/CD pipeline (not individual local machines) converts "a person made a mistake" into "a mistake that structurally can't reach production."
References
Related Questions
Last updated August 22, 2026 · Last reviewed August 22, 2026