Safeguard
Developer Tools•

Terraform prevent_destroy: what it protects and what it does not

prevent_destroy blocks plans that would destroy a resource, but not if you delete the block. How to use it with other safeguards for databases and state.

Safeguard Security Team
3 min read

prevent_destroy makes Terraform reject any plan that would destroy a resource. It is a seatbelt, not a lock. HashiCorp's documentation says it does not stop destruction if you remove the resource's configuration, so pair it with review rules, backups and narrow permissions.

What it does

Add a lifecycle block with prevent_destroy = true and Terraform errors on any plan that would destroy that object, including replacement that needs a destroy. The documentation says to use it sparingly, since it can also block terraform destroy and legitimate changes.

The gap

The protection lives in the configuration. If someone deletes the whole resource block, the flag goes with it, and there is nothing left to say the resource should be kept. The documentation states this directly: the rule does not prevent Terraform from destroying a resource if you remove its configuration.

A reviewer scanning a diff might also miss that a resource block disappeared, especially in a large refactor.

Layers that close the gap

  1. Review rules. Treat a deleted resource block for stateful resources as high-risk and require a named approver.
  2. Plan inspection. Automated checks on the plan can flag any destroy action against a list of protected types, such as databases, buckets and key stores.
  3. Narrow apply permissions. The pipeline role for production should not have permission to delete the highest-value resources. Cloud-side deletion protection settings on databases do this at the provider level.
  4. Backups and versioning. Assume deletion happens one day.
  5. Separate state for foundations. Keep long-lived data stores in their own root module with a stricter approval path.

Related lifecycle settings

HashiCorp's lifecycle page also covers rules that matter for safety:

  • ignore_changes skips updates to listed attributes after creation, so another process can manage them. That also hides drift on those attributes, so use it narrowly and note why.
  • create_before_destroy builds the replacement first, which reduces downtime but is limited by unique name requirements on some remote objects.
  • precondition and postcondition check assumptions before and after an operation. A postcondition failure prevents changes to dependent resources.

A good use of preconditions is asserting that a protected setting, such as encryption, is on before the apply goes ahead.

What a safe delete looks like

When you genuinely need to delete a protected resource:

  1. Take and verify a backup.
  2. Open a change with the reason and a rollback plan.
  3. Remove prevent_destroy in one reviewed change.
  4. Apply the destroy in a second change, so the intent is visible twice.

Cloud-side protection

Many cloud services offer their own deletion protection setting on databases and similar resources. It is enforced by the provider rather than by Terraform, so it still holds when a resource block is removed. Turn it on for production data stores, and note that you must switch it off deliberately, in a reviewed change, before a legitimate delete.

Quick check

Does prevent_destroy stop someone deleting the resource block?

No. If the configuration is removed, so is the flag. Use review rules, plan checks and narrow permissions as backup.

Should I put prevent_destroy on everything?

No. HashiCorp says to use it sparingly. Apply it to stateful or hard-to-recreate resources.

Sources

Last reviewed: 19 October 2026.

Never miss an update

Weekly insights on software supply chain security, delivered to your inbox.

Self-healing security runs on Safeguard.

Your first fix PR is minutes away.

No sales call required, even your agent can complete the purchase over MCP.