Migrate to RunxBuild and earn up to $50 in hosting credit on your first deposit.

Calculate your savings
unxBuild

Terraform Remove Block: Stop Managing a Resource Without Destroying It

Sean

Platform Writer

Jul 08, 2026
6 min read

The Terraform removed block (added in Terraform 1.1) tells Terraform to stop managing a resource without destroying the underlying object. The team that uses it cleanly hands off a resource to manual management, another tool, or another Terraform state file. The team that misuses it (or uses the older terraform state rm pattern) leaves orphaned resources in the cloud and loses track of what is and is not managed.

Terraform Remove Block: Stop Managing a Resource Without Destroying It

Table of contents

The problem: Terraform managing something it should not

The team that has been using Terraform for a year accumulates resources in state. Sometimes a resource needs to leave Terraform’s management - imported into another state, handed to a different team, kept running but no longer declared in code. The naive solution (delete the resource block from the .tf file and run terraform apply) makes Terraform want to destroy the resource.

The team that wants to stop managing a resource without destroying it has two options: the modern removed block (Terraform 1.1+) or the older terraform state rm command. The removed block is the recommended approach because it tracks the intent in code; terraform state rm modifies state outside the code review process.

Use case: handoff to another team or tool. A team that built infrastructure with Terraform, then migrated to Pulumi or Crossplane, needs to remove resources from Terraform state without destroying them. The removed block is the right tool.

The removed block syntax

Replace the resource block with a removed block, keeping the address the same. Example: replace resource "aws_instance" "web" { ... } with removed { from = aws_instance.web }. After terraform apply, the resource is removed from state and Terraform no longer manages it, but the actual EC2 instance keeps running.

The from attribute identifies the resource by its full address. The team that uses from = aws_instance.web removes that specific instance; the team that uses from = aws_instance.web["key"] (for resources with for_each or count) removes a specific instance from a set.

After running terraform apply with the removed block, run it again to verify no changes. The first apply removes the resource from state; the second apply should show no changes (because nothing in state references it). The team that sees continued changes has a leftover reference somewhere.

The lifecycle meta-argument alternative

For resources the team wants to keep in code but stop touching, use lifecycle { prevent_destroy = true } instead of removed. This is a different pattern: the resource stays in code and state, but Terraform refuses to destroy it. Useful for resources where accidental destruction would be catastrophic.

The team that uses prevent_destroy has an explicit ‘do not destroy’ signal in code. A reviewer seeing prevent_destroy = true knows the resource is protected. The team that has resources with no protection has Terraform that happily destroys them on a bad terraform apply.

Combine with ignore_changes for resources where the team wants Terraform to ignore drift. lifecycle { ignore_changes = [tags, ami] } tells Terraform to ignore changes to specific attributes - the resource stays in state but Terraform does not try to revert manual changes.

The terraform state rm alternative (older pattern)

Before Terraform 1.1, the only way to remove a resource from state without destroying was terraform state rm. Pattern: terraform state rm aws_instance.web. This removes the resource from state; Terraform no longer manages it; the actual cloud object keeps running.

The downside: state rm is a command, not code. The change does not show up in code review; the team has to track state changes via documentation or run logs. The team that uses state rm on production has a hard time auditing what was removed and why.

When to use state rm anyway: emergency situations. The team that needs to remove a resource from state immediately (CI pipeline is broken, the .tf files are lost) uses state rm as a one-off. The team that uses state rm as the primary pattern has untracked state changes that bite at audit time.

Workflow: the proper way to remove

Step 1: identify the resource and verify what it is. terraform state list | grep <pattern> shows resources matching the pattern. terraform state show <address> shows the resource details. The team that verifies first avoids removing the wrong resource.

Step 2: replace the resource block with a removed block. Keep the address (from = ...) the same. Add a comment explaining why the resource is being removed.

Step 3: run terraform plan and verify it shows ‘will be removed from state’. The team that sees ‘will be destroyed’ has the wrong block (resource, not removed) or the wrong syntax. The fix: correct the block before applying.

Step 4: run terraform apply to remove from state. The cloud object keeps running; Terraform no longer tracks it.

Step 5: run terraform plan again to verify no changes. The team that sees no changes has a clean state. The team that sees the resource being recreated has not removed it from state correctly.

Step 6: document the change. Add a comment in the .tf file or in team documentation explaining that this resource is now managed outside Terraform.

FAQ

What is the difference between removed block and terraform state rm?

The removed block is a declarative syntax in the .tf files - the change goes through code review. terraform state rm is a command that modifies state directly - the change is not in code. The team that uses the removed block has auditable changes; the team that uses state rm has untracked changes.

Does the resource get destroyed when I use removed?

No. The removed block tells Terraform to stop managing the resource without destroying the cloud object. The actual EC2 instance, S3 bucket, etc. keeps running. The team that wants to destroy the resource uses terraform destroy or deletes the resource block without replacing it.

Can I undo a removed block?

Yes - run terraform apply again with the original resource block restored (without the removed block). Terraform will re-import the resource if it still exists, or fail with ‘resource not found’ if it was deleted manually. The team that needs to re-import uses terraform import.

Does removed work with modules?

Yes. Use the full module address: removed { from = module.network.aws_vpc.main }. The team that uses modules references resources with the full module path.

What about resources with for_each or count?

Use the instance key: removed { from = aws_instance.web["key1"] }. The team that removes a specific instance from a for_each set uses the key; removing all instances at once is not supported by the removed block (use state rm for that).

Does removed work with Terraform Cloud?

Yes. The removed block is part of Terraform’s core functionality, not a CLI-only feature. The team that uses Terraform Cloud or Terraform Enterprise can use removed blocks in their code; remote runs handle them correctly.

How this fits the rest of the stack

For a sense of what the full project costs before it commits, the RunxBuild hosting calculator shows the line items together. The API, the database, the storage, the worker, the bandwidth - each one is a separate number, and the team’s mental model for the platform is the sum of those numbers.

Useful related references:

#terraform#iac#remove#state management