skip to content

In Terraform, how does running `terraform destroy` differ from deleting a resource block from the configuration and running `terraform apply`?

level: middleimportance: should knowfreq 50%

answer

  1. one edits code, one does not
  2. destroy leaves the definition behind
  3. state entry with no config gets removed
  4. reverse dependency order
  5. ephemeral environment versus retiring a component

basics

~20 s

terraform destroy proposes deleting everything this configuration currently manages, leaving the code untouched, so a later apply recreates it. Deleting a resource block changes the desired state permanently, so the next apply removes just that one object.

solid answer

~40 s

`terraform destroy` — which is simply `terraform apply -destroy` — plans the removal of every object recorded in this configuration's state, walking the dependency graph in reverse. Your `.tf` files are unchanged, so running `terraform apply` afterwards builds the whole environment back. It is the command for tearing down an ephemeral or review environment, not for retiring one resource. Deleting a resource block does something different in kind: it edits the desired state, so the next plan shows a single destroy for the object that is now in state without a matching configuration, and the change is durable because it lives in version control and goes through review. As a rule of thumb, destroy is a lifecycle action on an environment; removing a block is a change to the system's definition.

code

bash · 7 lines
bash
# tear down an ephemeral environment, code untouched
terraform plan -destroy -out=tfplan
terraform apply tfplan

# retire one component permanently: delete its block, then
terraform plan    # shows a single destroy for the orphaned state entry
terraform apply

go deeper

for a junior

Know that destroy tears down what this configuration manages while leaving the code intact, and that deleting a resource block makes the next apply remove just that object.

for a middle

Explain that an object is destroyed when it exists in state with no matching configuration, that destroy is apply -destroy in reverse dependency order, and that it can be planned and saved like any apply.

for a senior

Show the guardrails: separate state and credentials for production, protection on irreplaceable objects, reading the destroy count before approving, and never automating an unattended destroy against production.

for a principal

Own the blast-radius design — how state is partitioned so no single destroy can reach the whole estate, who holds credentials that permit one, and how ephemeral environments are created and reclaimed by policy.

## Two different things called "delete" Terraform decides what to do by comparing three things: the configuration, the state, and reality. An object gets destroyed whenever it exists in state but has no corresponding configuration telling Terraform to keep it. Both routes below produce destroys, but they arrive there differently and mean different things. ## Removing the block: a change to desired state Delete an `aws_s3_bucket` block, run `terraform plan`, and you see one destroy. Terraform found a state entry with no configuration behind it and concluded the object is no longer wanted. The important property is that this change is **durable and reviewable**. It is a diff in a pull request, someone approves it, it merges, and from then on the desired state simply does not include that bucket. Nothing will bring it back by accident. This is the normal way to retire infrastructure. ## `terraform destroy`: a lifecycle action on the whole configuration ```bash terraform destroy # equivalent to terraform apply -destroy ``` This proposes destroying **everything** in this configuration's state. The configuration is untouched — which is exactly why the environment comes straight back on the next `terraform apply`. That round-trip property is the point: it is the command for a stack whose whole existence is temporary. Because it is an apply variant, it behaves like one. It shows a plan first and prompts for `yes`, `-auto-approve` skips that prompt, and you can preview or save it: ```bash terraform plan -destroy -out=tfplan terraform apply tfplan ``` Saving a destroy plan is worth knowing — it is the one plan where reading the resource list before executing matters most. ## Ordering and blast radius A destroy walks the dependency graph in reverse: things that depend on other things go first. Terraform only touches what is in **this** configuration's state, so objects created by another root module, by another team, or clicked together in the console are invisible to it and survive. That is a genuine safety property, and it is also why splitting an estate into multiple states limits how much any single destroy can reach. ## The failure story interviewers are listening for The classic incident is someone running `terraform destroy` in the wrong working directory or against the wrong state, because the command looks like it belongs to the environment they had in mind. The guardrails people name in a good answer: - read the plan's resource list and the destroy count before typing `yes` — the confirmation prompt exists for this, - keep production in a separate state with credentials that developers do not routinely hold, - protect irreplaceable objects such as databases and data buckets so a destroy plan errors instead of proceeding, - never wire `-auto-approve` to a destroy in a pipeline that can be triggered against production. ## When you want the object gone from Terraform but *not* deleted There is a third case people conflate with these two: handing a resource over to another configuration or to another team without deleting the real thing. That is neither a destroy nor a plain block deletion — deleting the block alone would destroy the object — and Terraform has dedicated state-level mechanisms for it. Recognising that the case is distinct is the part that matters here; the mechanics belong to state management. ## Summary you can say out loud "Removing the block edits what I want the world to look like, permanently and in review. Destroy is a lifecycle action that removes everything this configuration currently manages while leaving the definition intact, so it can be rebuilt. I use destroy for ephemeral environments and block removal for retiring a component."

  • Is `terraform destroy` a distinct command or a variant of apply?
    It is a variant — `terraform destroy` is equivalent to `terraform apply -destroy`, and `terraform plan -destroy` previews it. That is why it behaves like any other apply: it shows a plan, prompts for confirmation, honours `-auto-approve`, and its plan can be saved with `-out` and applied later as a reviewed artefact.
  • After `terraform destroy`, what does the next `terraform apply` do?
    It rebuilds everything, because the configuration was never changed — only the state was emptied. New objects get new identifiers, so anything with generated names, addresses or attached data comes back different. That round-trip is why destroy suits ephemeral environments and is a poor fit for retiring a component you intend to stay gone.
  • Does `terraform destroy` delete resources it did not create?
    No. It only proposes destroying objects recorded in this configuration's state, so anything created by a different root module, another team, or by hand in the console is invisible to it. That is one practical reason to split a large estate across several states — it bounds how much any single mistaken destroy can reach.

saying these in an interview costs you the question

  • Thinks terraform destroy deletes everything in the cloud account
  • Believes destroy also removes the resource blocks from your code
  • Expects the same resources back with identical identifiers after a rebuild
  • Deletes a resource block expecting Terraform to just forget it
  • Wires destroy with -auto-approve into a production-capable pipeline

context