linuxlab.io
Tutorials▾
  • Linux & networking
    File system, processes, TCP/IP, BGP and OSPF
    →
  • Terraform & IaC
    HCL, state, plan/apply on a LocalStack sandbox
    →
  • Git & GitHub
    Object model, plumbing, branching, GitHub Actions
    →
All tutorials →
PricingAboutSign inCreate account
/
Intro
Lessons
Footer
linuxlab-TutorialsPricingAboutPrivacy & cookies
Copyright © 2026 LinuxLab. All rights reserved.
linuxlab.io
Tutorials▾
  • Linux & networking
    File system, processes, TCP/IP, BGP and OSPF
    →
  • Terraform & IaC
    HCL, state, plan/apply on a LocalStack sandbox
    →
  • Git & GitHub
    Object model, plumbing, branching, GitHub Actions
    →
All tutorials →
PricingAboutSign inCreate account
/
  • Introduction
  • Lessons
  • How it works
  • Knowledge base
  • Cheat sheet
  • Capstone
  • Interview prep
home/terraform/kb/Terraform basics/tf-destroy

kb/core ── Terraform basics ── beginner

terraform destroy: tear down everything you created

destroy removes every resource described in HCL and recorded in state. It is apply with a minus sign in front of everything. It is essential for learning tasks and ephemeral environments. In production it is a last resort.

view as markdown

What destroy does

terraform destroy is apply in reverse. It reads the state, sees every resource it once created, and deletes those resources through the cloud API. After destroy, the state is empty.

It is the equivalent of:

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

where N is every resource Terraform manages.

When it helps

  • Learning tasks. You experiment, tear it down, repeat. Nothing left behind.
  • Ephemeral environments. You bring up a preview environment for a PR, run the tests, tear it down.
  • End of a project. The client closed the project, so you run destroy and leave no dangling resources.
  • Rolling back a failed experiment. You created the wrong thing, run destroy, and start over.

What it looks like

bash
terraform destroy

Terraform shows a plan (like plan, but with minuses):

Terraform will perform the following actions:
  # aws_s3_bucket.demo will be destroyed
  - resource "aws_s3_bucket" "demo" {
      - bucket = "my-bucket-12345" -> null
      - tags   = { ... } -> null
      - id     = "my-bucket-12345" -> null
    }
Plan: 0 to add, 0 to change, 1 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:

Notice the phrase There is no undo. It is literally true: there is no rollback. Delete an S3 bucket and the data is gone. Delete an RDS instance and the snapshots are gone too (unless you set skip_final_snapshot = false).

Type yes. Terraform starts deleting in reverse dependency order. If a bucket references a KMS key, the bucket goes first, then the key.

Selective removal

Sometimes you need to tear down a single resource rather than everything:

bash
terraform destroy -target=aws_s3_bucket.demo

This is the equivalent of "remove only this block from HCL and run apply." You will rarely need it, but it can help, for example when a resource is stuck and recreating it is easier.

As an alternative, if you need to recreate a resource, prefer terraform apply -replace=aws_s3_bucket.demo. That means "tear it down and create it again in one apply."

Protection against accidental destroy: prevent_destroy

You can set a flag in the lifecycle block:

hcl
resource "aws_rds_instance" "prod_db" {
  # ... Parameters ...
  lifecycle {
    prevent_destroy = true
  }
}

Now terraform destroy (or any apply that tries to delete this resource) fails with an error. To actually tear it down, you first remove prevent_destroy = true, run apply, and only then run destroy.

This is production's best friend. See tf-resource-lifecycle.

Pitfalls

  • Destroy removes only what is in state. If the cloud holds resources created by hand (not Terraform), it leaves them alone.

  • Destroy does not delete the state file. After destroy, terraform.tfstate stays, but it is empty ("resources": []). If you want a clean slate, delete the file by hand.

  • Dependencies can block destroy. Say you have an S3 bucket with objects inside it. AWS will not let you delete the bucket without force_destroy = true in HCL. This is an AWS protection, not a Terraform one, and Terraform fails with a provider error.

  • destroy -target is a crutch. Reaching for -target regularly means your dependency graph is wrong.

  • Run destroy in CI with care. A separate pipeline for destroy is better, available to only a few people, with a second confirmation.

  • Auto-approve is dangerous. terraform destroy -auto-approve tears everything down without a second thought. In production, never.

Recovery after destroy

There is none. This is not git revert. If there was data, it is gone. So:

  • Back up before destroy (an RDS snapshot, S3 versioning, an EBS snapshot).
  • Put prevent_destroy = true on critical resources.
  • In production repositories, do not hand out destroy rights to just anyone.

§ команды

bash
terraform destroy

Tear down every resource in state with interactive confirmation.

bash
terraform destroy -auto-approve

No questions asked. Only for learning or ephemeral environments.

bash
terraform destroy -target=aws_s3_bucket.demo

Tear down one resource selectively. Use rarely.

bash
terraform plan -destroy

Show what would be torn down, without confirmation and without applying. A safe preview.

§ см. также

  • tf-applyterraform apply: apply a plan to a real cloudapply takes the result of plan and actually calls the cloud API: it creates, changes, and deletes resources. After apply, the state is updated. This is the command that turns money into infrastructure.
  • tf-planterraform plan: see what Terraform is about to doplan is a dry run: Terraform reads your HCL, reads the state, and shows the diff between them. It changes nothing in the cloud. This is your main tool for not breaking prod by mistake.
  • tf-stateState: Terraform's memory of what it createdState is the JSON file `terraform.tfstate` where Terraform records what it created in the cloud. Without it, Terraform would have no way to tell which bucket is "its own" and which belongs to something else. The file holds resource IDs, all attributes, and often secrets. It is the most sensitive part of any project.
  • tf-resource-lifecyclelifecycle: controlling resource behaviorThe lifecycle block configures four behaviors: create_before_destroy (zero-downtime replacement), prevent_destroy (deletion guard), ignore_changes (ignore drift on specific attributes), replace_triggered_by (force replacement on an external signal).
Footer
linuxlab-
Copyright © 2026 LinuxLab. All rights reserved.
Tutorials
Pricing
About
Privacy & cookies