Skip to main content
In this lesson we cover the Terraform prevent_destroy lifecycle meta-argument: what it does, when to use it, and how to handle cases where a protected resource must be intentionally removed or replaced. This is especially useful for protecting critical Azure resources such as production storage accounts, databases, and Key Vaults. Two core behaviors of prevent_destroy:
  • It prevents accidental deletion of critical resources. If a planned change would cause a resource to be destroyed, Terraform refuses to perform that destruction.
  • Terraform surfaces an explicit error during the plan phase if destruction is detected. This ensures terraform apply cannot silently delete the resource — it forces an intentional decision.
The image explains two functions: preventing accidental deletion of critical resources and causing Terraform to throw an error if a resource is planned for destruction.
Use case overview
  • Protect production-grade resources from accidental or automatic removal during refactoring or configuration changes.
  • Add an extra safety layer in your IaC pipeline beyond cloud provider delete locks (e.g., Azure Delete Lock), implemented at the Terraform level.
prevent_destroy causes plan-time failures when a resource would be destroyed. Always run terraform plan and review the output before applying in production to prevent unexpected interruptions.
Example: Protect an Azure Storage Account with prevent_destroy
What happens with the configuration above
  • Creation: Running terraform apply creates the resource normally.
  • Replacement: If later you change a property that requires replacement (for example changing account_replication_type from LRS to ZRS), the plan will attempt to destroy the existing storage account and create a new one. Because prevent_destroy = true is set, Terraform aborts the plan and reports an error.
Typical commands and sample outputs Initialization:
Sample init output (truncated):
Create resources:
Sample apply output (truncated):
Planned replacement blocked by prevent_destroy: If you change a property that requires replacing the storage account and then run terraform plan or terraform apply, you will see an error similar to this:
Sample plan error:
When to use prevent_destroy (summary table) How to intentionally remove or replace a protected resource
  • Update the lifecycle block: set prevent_destroy = false (or remove the block), run terraform plan and then terraform apply again. This is the safest, most explicit path.
  • Targeted plans: use -target to reduce the scope of evaluation. Note: -target does not bypass prevent_destroy for resources that are planned to be destroyed — it simply limits what Terraform evaluates.
  • Remove from state as a last resort: run terraform state rm <resource> and then delete the resource outside of Terraform. This makes Terraform forget the resource and is potentially dangerous for production-managed resources — use with care and approvals.
prevent_destroy is a safety mechanism. Do not circumvent it lightly for production resources. If destruction is truly required, make the removal explicit (for example, by modifying the lifecycle block) and ensure appropriate approvals are in place.
Comparing prevent_destroy to Azure Delete Lock
  • prevent_destroy is implemented at the Terraform/IaC layer and prevents Terraform from planning a destroy.
  • Azure Delete Locks are enforced by the Azure control plane and block deletion operations regardless of tool. Using both provides defense in depth: the lock protects resources from accidental deletion through any client, while prevent_destroy prevents accidental deletion as a result of Terraform workflows.
Links and references Further reading
  • Best practices for protecting production infrastructure in GitOps/IaC pipelines
  • Strategies for data migration and in-place upgrades to avoid destructive replacements

Watch Video