terraform destroy
terraform destroy removes all infrastructure resources managed by the current Terraform configuration. It’s the reverse of apply — instead of creating or updating, it tears everything down. Used correctly, it’s a powerful tool for cleaning up ephemeral environments. Used carelessly in production, it’s catastrophic.
Basic Usage
terraform destroyTerraform shows a destruction plan and requires confirmation:
Plan: 0 to add, 0 to change, 5 to destroy.
Do you really want to destroy all resources? Terraform will destroy all your managed infrastructure, as shown above. There is no undo. Only 'yes' will be accepted to confirm.
Enter a value: yesThe destruction order is the reverse of the creation order — Terraform respects dependency relationships and destroys dependents before their dependencies.
Targeted Destruction
Remove a single resource without affecting the rest of the infrastructure:
# Destroy a specific resourceterraform destroy -target=aws_instance.old_server
# Destroy a whole moduleterraform destroy -target=module.dev_database
# Destroy multiple specific resourcesterraform destroy -target=aws_instance.web -target=aws_eip.web_ipKey Flags
# Skip confirmation (dangerous — use only in automated teardown scripts)terraform destroy -auto-approve
# Pass variablesterraform destroy -var="environment=staging"terraform destroy -var-file="environments/dev.tfvars"
# Preview what would be destroyed without destroyingterraform plan -destroy
# Limit parallelismterraform destroy -parallelism=5Protecting Critical Resources from Destruction
Terraform provides lifecycle protections to prevent accidental destruction:
prevent_destroy
resource "aws_db_instance" "production_db" { identifier = "prod-postgres" engine = "postgres" instance_class = "db.r6g.large" allocated_storage = 100
lifecycle { prevent_destroy = true # terraform destroy will ERROR — won't proceed }}Error: Instance cannot be destroyed││ Resource aws_db_instance.production_db has lifecycle.prevent_destroy set,│ but the plan calls for this resource to be destroyed.ignore_changes
resource "aws_instance" "app" { ami = data.aws_ami.latest.id instance_type = "t3.medium"
lifecycle { ignore_changes = [ami] # Don't destroy/recreate when AMI is updated externally }}Safe Teardown Workflow for Environments
# 1. Preview what will be destroyedterraform plan -destroy -out=destroy-plan
# 2. Review — confirm no production resources are in scopeterraform show destroy-plan
# 3. Create a backup if needed (for databases, S3, etc.)aws rds create-db-snapshot --db-instance-identifier dev-db --db-snapshot-identifier dev-db-final-snapshot
# 4. Apply the destructionterraform apply destroy-plandestroy vs. Removing from Config
Two ways to stop managing a resource:
| Approach | What Happens |
|---|---|
terraform destroy -target=resource | Deletes the real resource AND removes from state |
Remove resource block from config, then apply | Same — Terraform sees the resource missing from config and destroys it |
terraform state rm resource | Removes from state only — real resource STAYS, Terraform forgets about it |
Use terraform state rm when you want to stop managing a resource without deleting it (hand it off to another team, another state file, or manual management).
destroy in CI/CD: Ephemeral Environments
One of the most powerful uses of destroy is automated teardown of pull request environments:
on: pull_request: types: [closed]
jobs: destroy: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4
- name: Terraform Init run: terraform init -input=false env: TF_WORKSPACE: pr-${{ github.event.number }}
- name: Terraform Destroy run: terraform destroy -auto-approve -var="pr_number=${{ github.event.number }}"This pattern spins up a fresh environment for each PR and tears it down automatically when the PR is closed — keeping costs low and environments clean.
What destroy Does NOT Delete
terraform destroy only removes resources tracked in the current state file. It will NOT delete:
- Resources created by other Terraform configurations (different state files)
- Resources created manually outside Terraform
- S3 bucket contents (the bucket is deleted but contents must be emptied first)
- RDS automated backups (retained per retention policy even after instance deletion)
Recovery from Accidental destroy
If you accidentally destroy resources:
- If using Terraform Cloud or versioned S3 backend: access the previous state version
- Re-run
terraform apply— Terraform will recreate all destroyed resources from config - Restore data from backups (Terraform recreates the infrastructure, not the data)
This is why remote state with versioning and prevent_destroy on stateful resources is not optional — it’s essential.