terraform destroy
terraform destroy removes every resource that Terraform currently manages in a workspace, deleting cloud infrastructure in the correct dependency order. It is the inverse of terraform apply: instead of reconciling state toward your configuration, it reconciles state toward empty. Because it is irreversible for most resources, destroy is the command you reach for when tearing down ephemeral environments, cleaning up after a CI run, or decommissioning a stack — and the one you must guard most carefully in production.
How destroy works
When you run terraform destroy, Terraform builds a destroy plan. It reads the current state, walks the resource dependency graph in reverse (children before parents), and proposes a deletion for every managed resource. The plan is shown for review and, by default, requires interactive approval before anything is deleted.
terraform destroy
Output:
aws_instance.web: Refreshing state... [id=i-0a1b2c3d4e5f6a7b8]
aws_security_group.web: Refreshing state... [id=sg-0123456789abcdef0]
Terraform will perform the following actions:
# aws_instance.web will be destroyed
- resource "aws_instance" "web" {
- ami = "ami-0c7217cdde317cfec" -> null
- instance_type = "t3.micro" -> null
- id = "i-0a1b2c3d4e5f6a7b8" -> null
}
# aws_security_group.web will be destroyed
- resource "aws_security_group" "web" {
- id = "sg-0123456789abcdef0" -> null
- name = "web-sg" -> null
}
Plan: 0 to add, 0 to change, 2 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:
Resources are deleted in reverse dependency order so that, for example, the EC2 instance is removed before the security group it references. Typing yes executes the deletions; anything else aborts. To skip the prompt in automation, pass -auto-approve — but only where a human has already reviewed the plan or the workspace is genuinely disposable.
terraform destroy -auto-approve
Warning:
terraform destroydeletes real infrastructure and there is no undo. Always read the plan, confirm you are pointed at the right workspace (terraform workspace show), and never wire-auto-approveinto a pipeline that can touch production.
terraform destroy is fully supported by OpenTofu (tofu destroy) with identical semantics and flags.
Previewing a destroy plan
You can generate and save a destroy plan without executing it by combining terraform plan with the -destroy flag. This is useful in code review or change-management workflows where the teardown must be approved before it runs.
terraform plan -destroy -out=teardown.tfplan
terraform apply teardown.tfplan
Saving the plan to a file guarantees that the exact set of deletions you reviewed is what gets applied, even if state drifts in between.
Targeting a subset of resources
To destroy only specific resources rather than the entire workspace, use -target. The address can be a single resource, a module, or an indexed instance. Terraform still respects dependencies, so anything that depends on the target is destroyed too.
terraform destroy -target=aws_instance.web
terraform destroy -target='module.cache' -target='aws_s3_bucket.tmp[0]'
Tip:
-targetis an escape hatch for exceptional situations, not a routine workflow. It can leave state inconsistent with configuration because Terraform skips the normal full-graph reconciliation. Prefer refactoring your configuration (for example, removing acountinstance) and running a normal destroy.
Guarding resources with prevent_destroy
The prevent_destroy lifecycle argument is a hard safety net. When set, any plan that would delete the resource — whether from terraform destroy, a -target, or a config change — fails immediately with an error instead of proceeding.
resource "aws_s3_bucket" "logs" {
bucket = "acme-prod-audit-logs"
lifecycle {
prevent_destroy = true
}
}
Output:
Error: Instance cannot be destroyed
on main.tf line 1:
1: resource "aws_s3_bucket" "logs" {
Resource aws_s3_bucket.logs has lifecycle.prevent_destroy set, but the plan
calls for this resource to be destroyed.
To actually destroy a guarded resource you must first remove or comment out the prevent_destroy block, then plan again. This deliberate two-step protects stateful resources like databases, S3 buckets, and KMS keys from accidental deletion.
Safe teardown of ephemeral environments
Destroy shines for short-lived environments — per-pull-request preview stacks, integration test fixtures, and demo sandboxes. Use a dedicated workspace per environment so a teardown can never touch another environment’s state.
terraform workspace select pr-1423
terraform destroy -auto-approve -var-file=envs/preview.tfvars
terraform workspace delete pr-1423
A typical CI teardown job runs in the workspace’s own remote backend, applies a strict input file, and tears everything down once the PR merges or closes. Because the workspace is isolated, -auto-approve is acceptable here.
Common destroy flags
| Flag | Purpose |
|---|---|
-auto-approve | Skip the interactive confirmation prompt |
-target=ADDR | Restrict the destroy to a resource, module, or instance (repeatable) |
-var-file=FILE | Supply input variables needed to resolve the configuration |
-refresh=false | Skip refreshing state before planning the destroy |
-lock-timeout=DURATION | Wait for a held state lock instead of failing immediately |
-parallelism=N | Limit concurrent destroy operations (default 10) |
Best Practices
- Always review the destroy plan and confirm
terraform workspace showbefore approving — there is no undo. - Reserve
-auto-approvefor genuinely disposable, isolated workspaces such as CI preview environments. - Put
prevent_destroy = trueon stateful, high-value resources (databases, log buckets, KMS keys) so accidental deletes fail loudly. - Use
-targetonly as an exception; prefer refactoring configuration and running a full destroy to keep state consistent. - Isolate each ephemeral environment in its own workspace and backend so a teardown can never affect another stack.
- For change-controlled teardowns, save the plan with
terraform plan -destroy -out=...and apply the exact reviewed file.