In this article, we’ll cover how to run terraform destroy safely through Atlantis PRs.
What “Atlantis destroy” means?
Atlantis doesn’t have a dedicated atlantis destroy command. In practice, “Atlantis destroy” means generating a destroy plan and then applying that plan through the normal PR workflow.
In Terraform terms, terraform destroy removes infrastructure managed by your configuration. Under the hood, it’s effectively the same as running terraform apply -destroy, and you can preview the impact with terraform plan -destroy.
Atlantis follows that same idea, but wraps it in PR comments: you run a destroy-mode plan, review it in the PR, then run apply to execute the already-generated planfile. Atlantis documents this as passing -destroy to atlantis plan.
How Atlantis destroy works in practice
A typical Atlantis destroy workflow follows the same two-phase model: plan, then apply.
- A user opens a PR (or comments a command on an existing PR).
- Atlantis checks out the PR code and runs Terraform on the Atlantis server.
- When
atlantis planruns, Atlantis locks the Terraform directory/workspace so other PRs can’t plan against the same state at the same time. That lock typically stays until the PR is merged or closed, or the plan is discarded. If you decide not to proceed, comment atlantis unlock to release the lock without merging. - With
-destroy, Terraform produces a planfile that represents deletions. Atlantis stores planfiles on disk, so if the server loses that data between plan and apply, you’ll need to rerun the plan. - When
atlantis applyruns, Atlantis applies the plan matching the directory, project, and workspace you target. If you runatlantis applywith no selector, Atlantis applies all unapplied plans from that PR.
The simplest destroy workflow in Atlantis
This is the most common and safest pattern because it’s one-off and explicit.
In a PR comment, run a destroy plan:
atlantis plan -- -destroy
If your repo has multiple Terraform projects, be specific about what you’re destroying:
# By directory atlantis plan -d infra/dev -- -destroy # By Atlantis project name atlantis plan -p project1 -- -destroy # By Terraform workspace atlantis plan -w staging -- -destroy
Note: -p cannot be used at the same time as -d or -w.
After reviewers approve and you’re confident the plan is correct, apply it using the same selector you planned with:
atlantis apply -d infra/dev # or atlantis apply -p project1 # or atlantis apply -w staging
In the PR, you’ll see normal Terraform plan output, except the summary will be destruction-only, for example:
Plan: 0 to add, 0 to change, 12 to destroy.
Because a destroy plan can delete important resources, this flow is intentionally manual and review-driven.
How to configure a dedicated Atlantis destroy workflow
Sometimes you want a named, consistent destroy workflow so teams don’t improvise commands. In Atlantis, that means creating a custom workflow that runs terraform plan with -destroy.
Atlantis supports custom workflows defined server-side (in repos.yaml) or repo-level (in atlantis.yaml). In most oranizations, it is simplest to define the destroy workflow server-side and let repos only select it.
Step 1: Allow workflow selection (and optionally custom workflows)
In many organizations, the Atlantis server prevents repositories from choosing or defining their own workflows because workflows are security-sensitive.
- If you want repos to select a workflow in
atlantis.yaml, the server-side repo config must allow theworkflowkey viaallowed_overrides. - If you want repos to define workflow steps in
atlantis.yaml, the server-side repo config must also setallow_custom_workflows: true.
A typical server-side repos.yaml pattern looks like this, with an explicit allowlist so a repo can’t select an unexpected workflow name:
# repos.yaml (server-side) repos: - id: /.*/ allowed_overrides: [workflow, apply_requirements, plan_requirements] allowed_workflows: [default, destroy] allow_custom_workflows: false workflows: destroy: plan: steps: - init - plan: extra_args: ["-destroy"] apply: steps: - apply
This is often safer than letting every repo define arbitrary workflows, because the server defines the steps and the repo can only select from an allowlisted workflow name.
Step 2: Add an explicit destroy project in atlantis.yaml
At the repo level, atlantis.yaml is where you define projects and optionally attach workflows to them. Once you define one or more projects, Atlantis stops autodiscovering projects unless you explicitly enable autodiscovery.
If you still want Atlantis to discover additional projects, you can enable it like this:
autodiscover: mode: enabled
A practical pattern is to define a second project that points at the same Terraform directory/workspace but uses a different workflow and has autoplan disabled. Disabling autoplan is important because you usually don’t want a destroy plan to run automatically just because someone opened a PR.
Here’s a complete example that defines a normal project and a destroy project for the same directory. It also adds stricter requirements so the PR must be approved and in a good state before Atlantis will apply:
# atlantis.yaml (repo-level) version: 3 projects: - name: app-prod dir: infra/app workspace: prod autoplan: enabled: true when_modified: ["**/*.tf", "**/*.tfvars", ".terraform.lock.hcl"] - name: app-prod-destroy dir: infra/app workspace: prod autoplan: enabled: false plan_requirements: [approved, mergeable, undiverged] apply_requirements: [approved, mergeable, undiverged] workflow: destroy workflows: destroy: plan: steps: - init - plan: extra_args: ["-destroy"] apply: steps: - apply
These plan_requirements and apply_requirements only take effect if the Atlantis server allows those keys via allowed_overrides.
If your destroy workflow is defined server-side in repos.yaml, you do not need to define workflows again inside atlantis.yaml.
Why extra_args: ["-destroy"] matters: Atlantis will still run a normal plan unless you tell it to pass -destroy to Terraform. Atlantis documents extra_args as the supported way to permanently add flags to plan/apply steps inside a custom workflow.
If you use variable files, you can include them the same way, for example:
extra_args: ["-destroy", "-var-file=prod.tfvars"]
Step 3: Run the destroy workflow from a PR comment
Atlantis commands are triggered by PR comments. You typically run plan first, review the output, then apply.
atlantis plan -p app-prod-destroy
After reviewers confirm the plan is correct and approvals are in place:
atlantis apply -p app-prod-destroy
If automerge is enabled in your setup, Atlantis lets you disable it for a single apply command:
atlantis apply -p app-prod-destroy --auto-merge-disabled
The key benefit of this approach is that destruction is visible as standard Terraform plan output in the PR, which is easier to review and audit than running terraform destroy directly.
Guardrails for safe destruction
A destroy workflow is easy to misuse, so we usually recommend at least one safety layer:
- Require approvals before apply. Atlantis can block
atlantis applyuntil the PR meets requirements likeapproved,mergeable, orundiverged. - Restrict who can run apply. Even with apply requirements, once they’re satisfied, anyone who can comment on the PR can usually run
atlantis apply. If you need “only a specific team can apply destroys,” use Atlantis repo/project permissions and authorization controls. - Be deliberate about where workflows live. Atlantis reads
atlantis.yamlfrom the PR branch. Allowing repo-defined custom workflows can increase risk because workflow steps can be security-sensitive. Many teams only allow workflow selection, or only define workflows server-side.
Using Spacelift to make “destroy” more controlled
If your destroy workflow is starting to accumulate extra process, Spacelift can be a cleaner way to keep deletion workflows explicit without turning your platform team into the “team of no.”
Spacelift is built around a two-path deployment model: a rigorous IaC & GitOps path for production-grade workflows, and a faster Intent path for non-critical work. Both under the same guardrails, governance, and visibility.
Where that helps with destructive changes:
- Policy as code guardrails around deletes. You can require additional approvals (or block) runs that include deletions, and enforce consistent rules across environments.
- Central audit trails you can actually use. Spacelift logs actions with identity, timestamps, and metadata, and can forward logs to external systems for retention and investigations.
- Drift detection to reduce “surprise” destruction. If your real environment has drifted from what code expects, deletion plans can get riskier. Spacelift’s drift detection helps you spot that early and control how remediation runs happen.
- Run inside your security perimeter. Private workers and dynamic credentials let you keep execution where your compliance program expects it.
This is also where teams that started with Atlantis sometimes land as they scale. Duolingo, for example, moved from Atlantis to Spacelift after hitting stability and scaling constraints, and reported going from five days to a few hours for applies across 500 directories.
Key points
“Atlantis destroy” means: run atlantis plan -- -destroy, review the plan output in the PR, then run atlantis apply against that same directory/project/workspace selector.
As a best practice, keep destruction explicit: disable autoplan for destroy projects, require approvals, and avoid “apply everything” patterns unless you truly mean it.
If deletion workflows are turning into a patchwork of scripts and exceptions, Spacelift can give you clearer guardrails, policy as code, audit trails, drift detection, and the two-path deployment model, without sacrificing visibility or governance.
To try out Spacelift and further enhance your workflow, create a free account here, and book a demo to speak with one of our engineers.