How to Use Terraform prevent_destroy to Protect Critical Infrastructure from Accidental Deletion

Set prevent_destroy = true inside a lifecycle block within any Terraform resource to block accidental destruction during plan and apply operations.

The terraform prevent_destroy lifecycle argument acts as a critical safety mechanism for infrastructure resources managed by HashiCorp Terraform. When enabled, this meta-argument prevents Terraform from destroying protected resources even if configuration changes or explicit destroy commands would normally remove them. Understanding how to implement and manage this protection requires examining the actual implementation in the hashicorp/terraform repository.

Understanding the Terraform prevent_destroy Lifecycle Meta-Argument

The prevent_destroy argument is part of Terraform's lifecycle meta-argument block, which controls how Terraform manages specific resource instances during create, update, and destroy operations.

How prevent_destroy Works Under the Hood

According to the hashicorp/terraform source code, the protection mechanism operates in three distinct phases:

  1. Configuration Parsing: When Terraform parses your configuration files, the lifecycle block containing prevent_destroy is decoded in internal/configs/resource.go. The parser stores this flag in the resource's managed meta-state as Managed.PreventDestroy.

  2. Plan Validation: During the planning phase, Terraform constructs a graph of proposed actions. Each resource instance node (NodeAbstractResourceInstance) executes the checkPreventDestroy method defined in internal/terraform/node_resource_abstract_instance.go. This method inspects the planned action and the stored flag.

  3. Error Generation: If the planned action involves destruction (including replacement operations that require deletion) and prevent_destroy is set to true, Terraform returns a diagnostic error that halts the plan execution. The error message instructs users to either remove the protection or narrow the plan scope using -target.

Implementing Terraform prevent_destroy in Your Configuration

Adding protection to critical resources requires minimal syntax changes to your Terraform configuration files.

Basic Syntax and Usage

Place the lifecycle block inside any resource definition and set prevent_destroy = true:

resource "aws_s3_bucket" "production_logs" {
  bucket = "company-production-logs"
  
  tags = {
    Environment = "production"
    Critical    = "true"
  }

  lifecycle {
    prevent_destroy = true
  }
}

This configuration prevents accidental destruction of the S3 bucket even if someone removes the resource block from the configuration or runs terraform destroy.

Verifying Protection with Terraform Plan

After applying the configuration with prevent_destroy enabled, attempt to destroy the resource to verify the protection works:


# This will fail with an error

terraform plan -destroy -target=aws_s3_bucket.production_logs

Terraform outputs an error similar to:


Error: Instance cannot be destroyed
Resource aws_s3_bucket.production_logs has lifecycle.prevent_destroy set,
but the plan calls for this resource to be destroyed. To avoid this error,
continue to use the resource in your configuration, or remove the
lifecycle.prevent_destroy setting.

Bypassing prevent_destroy When Necessary

While the protection is designed to prevent accidents, legitimate scenarios require destroying protected resources. The hashicorp/terraform source code provides specific mechanisms for these situations.

Configuration-Level Override

The standard method for removing protection involves modifying the configuration:

  1. Remove the lifecycle block entirely, or
  2. Set prevent_destroy = false:
resource "aws_s3_bucket" "production_logs" {
  bucket = "company-production-logs"
  
  lifecycle {
    prevent_destroy = false  # Protection removed

  }
}

After applying this change, destruction operations will proceed normally.

Targeted Destruction and Internal Overrides

According to internal/terraform/context_plan.go, Terraform supports an OverridePreventDestroy option within PlanOpts. This boolean flag is reserved for internal use and specific edge cases:

  • Destroy-only plans: When running terraform destroy -target=..., Terraform can set this override to allow destruction of specifically targeted protected resources while maintaining protection for others.
  • Test harnesses: The Terraform test framework uses this option to clean up resources after test completion.

Normal user workflows cannot access this override directly through CLI flags. The intended user-facing approach for destroying protected resources remains modifying the configuration or using targeted operations that respect the lifecycle constraints.

Summary

  • Terraform prevent_destroy is a lifecycle meta-argument that blocks destruction of critical resources during plan and apply operations.
  • The protection mechanism parses the lifecycle block in internal/configs/resource.go and validates destruction attempts in internal/terraform/node_resource_abstract_instance.go via the checkPreventDestroy method.
  • When enabled, any plan that would destroy or replace the protected resource fails with a diagnostic error, forcing explicit configuration changes to proceed.
  • To destroy a protected resource, either remove the prevent_destroy argument from the configuration or use targeted destruction workflows that leverage internal override mechanisms reserved for specific use cases.
  • The OverridePreventDestroy option in internal/terraform/context_plan.go exists for internal tooling and destroy-target operations, but standard users should modify configuration files to remove protection.

Frequently Asked Questions

What happens if I try to destroy a resource with prevent_destroy set to true?

Terraform halts the plan execution and returns an error stating that the resource has lifecycle.prevent_destroy set, but the plan calls for destruction. The error message instructs you to either continue using the resource in your configuration or remove the prevent_destroy setting. This check occurs in internal/terraform/node_resource_abstract_instance.go within the checkPreventDestroy method.

Can I override terraform prevent_destroy without modifying the configuration?

Standard CLI workflows require modifying the configuration to remove protection. However, Terraform's internal planning engine in internal/terraform/context_plan.go supports an OverridePreventDestroy flag within PlanOpts that bypasses the check. This override is reserved for internal use cases such as terraform destroy -target operations and test framework cleanup, and is not exposed as a user-facing command-line flag.

Does prevent_destroy protect against resource replacement?

Yes. Terraform treats replacement operations as a delete followed by a create. The checkPreventDestroy method in internal/terraform/node_resource_abstract_instance.go checks if the planned action includes a delete operation. If prevent_destroy is enabled and the plan requires replacement (which destroys the existing instance), Terraform blocks the operation with the same error used for pure destruction.

Where is the prevent_destroy setting stored in the Terraform state?

The prevent_destroy value is not stored in the Terraform state file itself. Instead, it is parsed from the configuration during the decoding phase in internal/configs/resource.go and stored in the resource's managed meta-state (Managed.PreventDestroy) within the internal configuration representation. Terraform evaluates this flag during the planning phase by checking the configuration meta-state against the planned actions, not by referencing the state file.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →