Skip to content
DevOps AI ToolKit
Newsletter
All guides
AI for Terraform By James Joyner IV · · 9 min read

Forgetting Terraform Resources With the removed Block (Without Destroying Them)

The removed block can destroy a resource or just forget it — and one line of HCL separates the two. Here's how to drop resources from Terraform management while leaving the real infra running.

  • #terraform
  • #ai
  • #removed-block
  • #state
  • #refactoring

There’s a class of Terraform operation that has nothing to do with changing infrastructure and everything to do with changing who manages it. You’re handing a resource to another tool, splitting one config into two, or deprecating a module — and you want Terraform to stop tracking a resource while the real thing keeps running, untouched.

For years that meant terraform state rm: an imperative CLI command with no plan to review and no record in your code. The removed block replaces it with something declarative and reviewable. But the removed block has a sharp edge: depending on one line, it either forgets a resource or destroys it. Get that line wrong and you delete live infrastructure.

Two behaviors, one line apart

A bare removed block destroys the resource:

# DANGER: this DESTROYS the real resource
removed {
  from = aws_s3_bucket.legacy
}

Add lifecycle { destroy = false } and it merely forgets it — Terraform drops it from state, the bucket keeps existing:

# SAFE: forget only — the bucket stays, Terraform stops managing it
removed {
  from = aws_s3_bucket.legacy
  lifecycle {
    destroy = false
  }
}

That’s the whole game. When your intent is “stop managing this but leave it running” — which is almost always the intent when you reach for this — you need destroy = false. The forget-only variant is the modern, in-code replacement for terraform state rm.

When you actually want forget-only

The forget-only pattern shows up whenever ownership moves but the resource doesn’t:

  • Handing a resource to another state or tool — you’re migrating an S3 bucket from one Terraform config to another, or to a different IaC tool entirely.
  • Splitting a monolith — one config becomes two, and some resources need to leave the old state to be adopted by the new one.
  • Deprecating a module — you’re retiring the module but the resources it created must keep running until something else picks them up.

In all of these, destroying the resource would be an outage. You want Terraform to let go, not to delete.

Authoring the block

For each resource you want to forget, write a removed block with the correct address — including count/for_each instances and module-nested resources — and delete the corresponding resource block. The removed block replaces the resource declaration:

removed {
  from = module.storage.aws_s3_bucket.archive
  lifecycle {
    destroy = false
  }
}

removed {
  from = aws_iam_role.legacy["batch"]
  lifecycle {
    destroy = false
  }
}

If the resource block is still present, Terraform sees a conflict. Remove the resource, add the removed block.

Read the plan like your job depends on it

This is the step that turns a scary operation into a safe one. Run terraform plan and confirm it shows each resource being removed from state with no destroy or delete action:

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

  # aws_s3_bucket.legacy will no longer be managed by Terraform,
  # but will not be destroyed

If the plan shows any destroy, your destroy = false is missing or misplaced. Stop. Fix it. Do not apply a removed plan that wants to destroy something you intended to keep. Because removed blocks live in code and surface in the plan, this is a reviewable change — unlike state rm, which gives you no preview at all. Our removed block deletion planning prompt covers the intentional-destroy case, where you genuinely do want it gone.

Plan the re-adoption so nothing goes unmanaged

Forgetting is usually only half the move. The resource is going somewhere — another state, another tool — and there’s a window between “Terraform forgot it” and “the new owner adopted it” where nothing manages the resource at all. Sequence the handoff so that window is as short as possible and never leaves critical infrastructure untracked:

  1. Add import (or the new tool’s adopt step) on the receiving side, ready to go.
  2. Apply the removed block in the old config.
  3. Apply the import in the new config immediately after.

Order it so a brief unmanaged moment never lands on something that can’t tolerate it. Our Moved & Import Blocks prompt covers the adoption side.

Let AI draft it, then verify forget-not-destroy

Writing the blocks and sequencing the handoff is a good fit for an AI assistant — with the absolute requirement that you verify the plan forgets rather than deletes. A prompt like:

I want Terraform to stop managing aws_s3_bucket.legacy and module.storage.aws_s3_bucket.archive without destroying them — they’re moving to a separate config. Write the removed blocks, tell me which resource blocks to delete, and show exactly what the plan should say. Flag anything that would destroy a resource.

A trustworthy answer returns both blocks with destroy = false, the resource blocks to remove, and:

The plan must show “will no longer be managed… but will not be destroyed” and 0 to destroy. If you see any destroy, the destroy = false is missing — do not apply.

That refusal to apply a destroy is the safeguard. The AI writes the declarative blocks and the handoff order; you confirm the plan forgets without deleting before anything runs. Our removed block forget-only prompt is built around exactly this verify-first flow.

The one thing to remember

The removed block is two operations wearing the same name, separated by lifecycle { destroy = false }. When you mean “forget, not destroy,” that line is mandatory and the plan must show zero destroys. Treat it as a reviewable, in-code replacement for state rm, sequence the re-adoption so nothing goes unmanaged, and let AI draft while you verify. For more on safe Terraform refactors, browse our Terraform guides.

Free download · 368-page PDF

Download the Free 500-Prompt DevOps AI Toolkit

500 battle-tested, copy-paste AI prompts engineered by a senior systems engineer — every one with fill-in placeholders and safety/back-out notes. Drop your email and it's yours.

  • 500 prompts: Linux · Kubernetes · Terraform · OpenStack · GitLab · Docker · Monitoring · Incident Response
  • Instant PDF download — yours free, forever
  • Plus one practical AI-workflow email a week (no spam)

Single opt-in · unsubscribe anytime · no spam.