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 applycannot silently delete the resource — it forces an intentional decision.

- 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.prevent_destroy
- Creation: Running
terraform applycreates the resource normally. - Replacement: If later you change a property that requires replacement (for example changing
account_replication_typefromLRStoZRS), the plan will attempt to destroy the existing storage account and create a new one. Becauseprevent_destroy = trueis set, Terraform aborts the plan and reports an error.
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:
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), runterraform planand thenterraform applyagain. This is the safest, most explicit path. - Targeted plans: use
-targetto reduce the scope of evaluation. Note:-targetdoes not bypassprevent_destroyfor 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.prevent_destroy to Azure Delete Lock
prevent_destroyis 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_destroyprevents accidental deletion as a result of Terraform workflows.
- Terraform lifecycle meta-arguments: https://www.terraform.io/docs/language/meta-arguments/lifecycle.html
- Azure Resource Manager locks: https://learn.microsoft.com/azure/role-based-access-control/locking-resources
- Terraform Azure Provider (azurerm): https://registry.terraform.io/providers/hashicorp/azurerm/latest
- Best practices for protecting production infrastructure in GitOps/IaC pipelines
- Strategies for data migration and in-place upgrades to avoid destructive replacements