What this command does in detail
Running terraform destroy directly is shorthand for two steps combined: it computes a plan where every resource in state is marked for deletion (the same as terraform plan -destroy), shows it to you, and — after you confirm — applies that plan, deleting each resource from Azure in an order that respects dependencies (in reverse of how they were created).
This is the one command on this page with real, permanent consequences beyond infrastructure: destroying database.tf's PostgreSQL server deletes every row of data inside it, with no built-in undo. Back up anything that matters before running this against a database you care about.
Where to run it from working directory
terraform -chdir=terraform destroy
Note that this only ever affects the resources tracked by that folder's state. Running it inside terraform/ never touches terraform/bootstrap/'s resources — the state storage account and the Terraform deployment identity — because they live in a completely separate state file. Destroying bootstrap requires deliberately running the same command inside that folder instead.
Precondition what must already be true
- terraform init completed, connected to the same backend the resources were created through.
- Azure credentials with delete permission for every resource being removed.
- Any data you want to keep has already been backed up — destroy does not prompt you to export anything first.
- Nothing outside Terraform's knowledge still depends on the resources being removed (for example, a manually-created resource pointing at one of them).
Postcondition what becomes true after it succeeds
- Every resource that was tracked in this folder's state has been deleted from Azure.
- State is updated to reflect that nothing remains — an empty (or near-empty) state file.
- Any outputs that depended on the destroyed resources are no longer available.
- Resources belonging to a different state (like bootstrap's storage account and identity) are completely untouched.
How this project uses it real examples
args=()
if [[ "$OPERATION" == destroy ]]; then args+=(-destroy); fi
terraform -chdir=terraform plan -input=false -lock-timeout=5m "${args[@]}" -out workflow.tfplan
...
terraform -chdir=terraform apply -input=false -lock-timeout=5m workflow.tfplan
Selecting destroy in this project's GitHub Actions workflow never actually runs the bare terraform destroy command. Instead it runs terraform plan -destroy to produce a destroy-flavored plan, then terraform apply's that exact plan — the same reviewed-plan-then-apply pattern used for every other operation, so a destroy gets the identical safety guarantees (a plan captured in the job log, locking, no stale-plan risk) as a normal apply.
After the application infrastructure is destroyed, the bootstrap resource group, state storage account, and Terraform deployment identity are all still there — ready for the same project to be re-applied later without repeating the one-time bootstrap setup.
Common errors and how to fix them
| What you see | Likely cause | How to fix it |
|---|---|---|
| A resource fails to delete with a dependency conflict | Something outside Terraform's knowledge still references the resource (a manually created resource, or a lingering firewall rule). | Remove the external dependency first, then re-run destroy. |
| A resource is “not found” during destroy | It was already deleted outside of Terraform (for example, manually in the Portal). | Terraform generally treats this as already-satisfied and removes it from state; if it errors instead, run terraform state rm <address> to drop it from tracking manually. |
| “Error acquiring the state lock” | Another run is using the same state concurrently. | Wait for it to finish; this project's workflow concurrency group prevents overlapping infrastructure runs. |
| Data is gone after running this against the database | This is expected, correct behavior — destroy permanently deletes the PostgreSQL server and all its data. | Restore from a backup made beforehand; there is no way to recover data after the fact through Terraform. |