terraform destroy

By Vishvesh Patel · DevOps EngineerUpdated July 12, 2026

terraform destroy safely. Partial destroys with -target, reading the destroy plan, and when to decommission instead. Plus fmt and validate.

What Is terraform destroy?

terraform destroy removes all infrastructure resources managed by your Terraform configuration. It is the opposite of terraform apply.

terraform destroy

Terraform reads your configuration and state file, calculates a destroy plan (everything that exists gets removed), shows you the plan, and waits for approval before deleting anything.

Warning: terraform destroy is permanent. Deleted cloud resources cannot be recovered unless you have backups (e.g., RDS snapshots, EBS snapshots). Always review the destroy plan carefully.

The Destroy Plan

Before destroying anything, Terraform shows you exactly what will be deleted:

Terraform will destroy all your managed infrastructure, as shown below.
These resources will be destroyed in the proper reverse order.

  # aws_instance.web will be destroyed
  - resource "aws_instance" "web" {
      - ami           = "ami-0c55b159cbfafe1f0" -> null
      - instance_type = "t3.micro" -> null
      - id            = "i-0abc12345def67890" -> null
      - public_ip     = "54.123.45.67" -> null
    }

  # aws_security_group.web will be destroyed
  - resource "aws_security_group" "web" { ... }

  # aws_subnet.public will be destroyed
  - resource "aws_subnet" "public" { ... }

  # aws_vpc.main will be destroyed
  - resource "aws_vpc" "main" { ... }

Plan: 0 to add, 0 to change, 4 to destroy.

Do you really want to destroy all resources?
  Terraform will destroy all your managed infrastructure.
  There is no undo. Only 'yes' will be accepted to confirm.

  Enter a value: yes

Notice the reverse dependency order: Terraform destroys in the reverse of the creation order. The EC2 instance is destroyed before the security group, which is destroyed before the subnet, which is destroyed before the VPC. This prevents dependency errors (e.g., you cannot delete a VPC that still has running instances).

When to Use terraform destroy

Use CaseAppropriate?
Tearing down a dev/test environment✅ Perfect use case
Cleaning up after a tutorial or experiment✅ Perfect use case
Removing a feature branch environment✅ Standard practice
Decommissioning part of production⚠️ Use with extreme caution + backup strategy
"I'll just recreate it" in production❌ Almost always wrong

terraform destroy is most commonly used for ephemeral environments, dev environments, feature branch previews, CI/CD testing environments, and tutorial cleanup.

Partial Destroy with -target

To destroy a single resource (or module) without touching the rest:

# Destroy a single resource
terraform destroy -target=aws_instance.web

# Destroy an entire module
terraform destroy -target=module.database

Terraform will show a destroy plan for only the targeted resource:

  # aws_instance.web will be destroyed
  - resource "aws_instance" "web" {
      - id = "i-0abc12345def67890" -> null
    }

Plan: 0 to add, 0 to change, 1 to destroy.

Caution: -target can leave your state inconsistent. If other resources depended on the destroyed resource, they still exist in state but their dependency is gone. Always run a full plan after a targeted destroy to check for consistency.

Auto-Approve in CI/CD

Like apply, you can skip the confirmation with -auto-approve:

terraform destroy -auto-approve

This is commonly used in CI/CD pipelines to automatically tear down ephemeral environments:

# GitLab CI, destroy on branch delete
teardown:
  stage: destroy
  script:
    - terraform init -input=false
    - terraform destroy -input=false -auto-approve
  when: manual

Preview the Destroy Plan Without Destroying

To see the destroy plan without any risk, use terraform plan -destroy:

terraform plan -destroy

This is functionally equivalent to terraform destroy without the actual deletion, great for reviewing what would be destroyed before committing.

The destroy Lifecycle Hook

If you want certain resources to be retained even when the configuration is removed, use the prevent_destroy lifecycle argument:

resource "aws_s3_bucket" "critical_data" {
  bucket = "my-production-data"

  lifecycle {
    prevent_destroy = true
  }
}

If you try to destroy this resource (or remove it from your config), Terraform will error:

╷
│ Error: Instance cannot be destroyed
│ Resource aws_s3_bucket.critical_data has lifecycle.prevent_destroy set to true.
│ To allow this object to be destroyed, remove the lifecycle block or set
│ prevent_destroy = false.
╵

Use prevent_destroy for critical resources like production databases, S3 buckets with important data, or any resource where accidental deletion would be catastrophic.


terraform fmt, Format Your Code

While you have your terminal open, terraform fmt is a command you will use constantly:

terraform fmt

It automatically formats all .tf files in the current directory to match the Terraform style guide, consistent indentation, aligned = signs, and proper spacing.

# Format and show which files were changed
terraform fmt -diff

# Format all files recursively (including modules)
terraform fmt -recursive

# Check formatting without making changes (useful in CI)
terraform fmt -check

Example, before formatting:

resource "aws_instance" "web" {
ami = "ami-0c55b159cbfafe1f0"
instance_type = "t3.micro"
  tags = {
    Name = "web-server"
  }
}

After terraform fmt:

resource "aws_instance" "web" {
  ami           = "ami-0c55b159cbfafe1f0"
  instance_type = "t3.micro"
  tags = {
    Name = "web-server"
  }
}

Pro tip: Add terraform fmt -check to your CI pipeline. If anyone submits unformatted code, the pipeline fails, this enforces consistent style across the team without manual code review comments.


terraform validate, Validate Your Configuration

terraform validate checks your configuration for syntax errors and internal consistency:

terraform validate

Successful output:

Success! The configuration is valid.

Error example:

╷
│ Error: Unsupported argument
│   on main.tf line 8
│ An argument named "instanse_type" is not expected here.
│ Did you mean "instance_type"?
╵

validate catches:

  • Syntax errors (missing braces, typos)
  • References to undeclared variables or resources
  • Invalid attribute names for a resource type
  • Type mismatches (e.g., passing a string where a number is expected)

What validate does NOT check:

  • Whether the cloud credentials are valid
  • Whether the AMI ID exists in your region
  • Whether the VPC ID actually exists
  • Anything that requires calling cloud APIs
# Typical workflow before pushing code:
terraform fmt -recursive
terraform validate
terraform plan

Knowledge Check

Exercise

Question 1: Destroy Order

You have a VPC, a subnet inside the VPC, and an EC2 instance inside the subnet. When you run terraform destroy, in what order does Terraform destroy these resources?

Exercise

Question 2: prevent_destroy

A developer accidentally removes the aws_rds_cluster.production resource block from the Terraform config. What happens when they run terraform apply?

Exercise

Question 3: terraform fmt

Your CI/CD pipeline includes terraform fmt -check. A developer submits a merge request with an unformatted .tf file. What happens?


Frequently Asked Questions

What does terraform destroy actually delete?

Every resource recorded in the state file for that workspace and configuration. It does not touch resources created outside Terraform, and it does not touch other workspaces or other state files. The destroy plan is shown for approval first, and reading it is worth the time. The count of resources is the quickest sanity check that you are pointed at the environment you think you are.

How do I preview a destroy without actually destroying?

terraform plan -destroy produces the destroy plan without executing it, and -out saves it for review. This is the safe way to answer "what would go away", particularly before tearing down anything shared. In CI, generating a destroy plan and posting it for approval is the equivalent of the normal plan-then-apply flow.

How do I protect resources from accidental destruction?

Add lifecycle { prevent_destroy = true } to anything holding data. Terraform then refuses any plan that would destroy it, including a full terraform destroy, and you must remove the flag deliberately to proceed. Combine that with provider-level protection, RDS deletion protection, S3 bucket versioning and MFA delete, so a mistake has to get past more than one gate. Note prevent_destroy cannot stop a destroy triggered by the resource being removed from configuration entirely.

Can I destroy just one resource?

Yes, with terraform destroy -target=aws_instance.example, but treat it as a recovery tool rather than routine practice. Targeting operates on a subset, so the rest of your configuration is not reconciled and dependent resources may be left referencing something gone. A cleaner approach for permanent removal is to delete the resource from the configuration and run a normal apply, which Terraform plans with full dependency awareness.

What is the difference between terraform destroy and deleting resources in the console?

terraform destroy removes the resources and clears them from state, leaving everything consistent. Deleting in the console removes the resources but leaves state believing they exist, so the next plan shows Terraform intending to recreate them, which is drift, and at best confusing, at worst a surprise recreation of something expensive. If resources were removed outside Terraform, use terraform state rm to bring state back in line.

Should terraform destroy ever run automatically in CI?

Only for genuinely ephemeral environments. A per-pull-request preview stack that is torn down on merge, or a nightly cleanup of a sandbox account. Even then, scope it tightly with a separate state file and credentials that cannot reach production, so an error in the pipeline cannot destroy the wrong thing. For anything long-lived, destruction should require a human.

Continue Learning

Explore Related Topics

Try the Tool

Practise this in the browser

Terraform Playground

Run init, plan, apply and destroy against simulated infrastructure.

When it breaks

Related Resources