Terraform

Terraform removed Block Deep Dive: Declaratively Unmanage Resources

2026-04-19
NicheeLab Editorial Team

In Terraform, removing a resource definition from code normally schedules a destroy. That is a problem in operations when you want to keep the actual resource you created but stop managing it with Terraform.

The removed block is a declarative state operation that fills this gap. It replaces one-off CLI operations such as terraform state rm with code, letting you “forget” a resource in a reviewable and reproducible way.

Purpose and Use Cases of the removed Block

The removed block is a declaration that drops an existing managed resource from Terraform state management without destroying it. At apply time, no destroy is requested from the provider; only the corresponding state entry is removed. The real infrastructure resource stays in place.

Expected use cases include handing off log-storage buckets to another tool or manual operations, putting back into unmanaged state any temporary resources that were Terraform-managed only during validation, and removing entries from state in a team-reviewable fashion.

  • Expresses “forget” declaratively so it can be reviewed and tracked via diffs
  • Does not trigger destroy, so critical resources can be safely unmanaged
  • Re-running has no side effects (idempotent)

Syntax and Evaluation Timing

removed is a top-level block. In from, you specify “the address of the object that was previously managed.” count/for_each instances are supported via index/key specifications. At plan time, Terraform interprets the relevant state entry as a “state removal” rather than a destroy.

In terms of apply ordering, removed is processed as part of the normal diff resolution. If the target does not exist in state, nothing happens. After apply, you may delete the removed block itself from your code (it is a temporary declaration meant for migration).

  • Syntax: removed { from = "<address>" }
  • Target: instances of managed resources (e.g., aws_s3_bucket.logs or aws_instance.web[0])
  • Effect: deletes only the state entry without performing destroy

Plan and apply flow with removed

plan/apply: forget from stateno provider destroyTerraform configremoved { ... }Terraform stateremove addressprovider APIno destroy calledremoved only deletes from state and never calls destroy on the provider

Choosing Between removed and Other Approaches

removed is the tool for “taking a resource out of management.” Use moved for rename and address changes, terraform state rm for an immediate local-only state edit, and destroy when you actually want to delete the real infrastructure. This distinction is also a frequent exam topic.

In particular, note that merely deleting a resource definition from code schedules a destroy. Use removed in combination when you want to suppress destroy and forget the resource from state.

  • moved: declares an address change (from → to). The real resource is preserved; only the association in state is updated
  • removed: declares removal from management. The real resource is preserved; it is removed from state
  • terraform state rm: a one-off CLI state operation (not declarative, hard to put through review)
  • terraform destroy / -target: deletes the real resource. Does not turn it into an unmanaged resource
ApproachPrimary PurposeEffect on Real InfrastructureDeclarative / Review Fit
removed blockRemoves from management (forgets from state)Not deleted (resource remains)High (can stay in code)
moved blockChange resource/module addressNot deleted (resource preserved)High (trackable in code)
terraform state rmManually delete from stateNot deleted (resource remains)Low (ad-hoc command; weak reproducibility and reviewability)
terraform destroy / -targetDelete the real resourceDeleted (provider destroy)Medium (plan is visible but not retained as a declaration)

Real-world Scenario: Unmanage an S3 Log Bucket from Terraform

As an example, suppose aws_s3_bucket.logs (an audit log bucket) will from now on be managed directly by the security team. You want to remove it from Terraform’s scope but keep the actual bucket. Simply deleting it from code schedules a destroy, so you use removed.

After apply, the bucket disappears from state and subsequent plans no longer reference it from Terraform. If other resources reference it, first switch those references (to data sources, external inputs, variables, etc.) before applying.

  • When using count/for_each, you can pinpoint a specific instance to exclude (e.g., aws_iam_user.legacy["temp"])
  • Once apply completes and a no-op is confirmed, the removed block itself can be deleted (it is a temporary declaration)
  • Assumes Terraform 1.6 or later (in real projects, check the docs for the version you use)

HCL example: take an S3 bucket out of management

# Assumes Terraform >= 1.6
# Existing: aws_s3_bucket.logs is present in state

terraform {
  required_version = ">= 1.6.0"
}

# Previously this file defined aws_s3_bucket.logs but it has been removed

# We want to drop it from state without destroying it
removed {
  from = "aws_s3_bucket.logs"
}

# Example of removing a specific count/for_each instance
# removed {
#   from = "aws_iam_user.legacy[\"temp\"]"
# }

Design and Operational Considerations

Watch the order in which dependencies are resolved. If other resources reference the target of removed, plan fails due to a broken reference. Replace the references first (switch to data sources, external inputs, or avoid hardcoding) or split the apply into phases.

To preserve state consistency, the safe practice is to include removed in a PR, get it reviewed, confirm a no-op after apply, and then delete the removed block. If you also use CLI state rm, retain an audit log and runbook of who did what and when.

  • removed does not call the provider API (no destroy)
  • If the target is not in state, it is a no-op (safe to re-apply)
  • Works the same way in Terraform Cloud/Enterprise remote runs (evaluated per workspace)

Certification Exam Prep (Pro-level)

You are expected to clearly articulate the difference between removed and moved, and how they differ from destroy. In scenario questions, read “keep the real resource,” “take it out of management,” and “change the address” as cues, then pick the right block or command.

Other common topics include specifying individual count/for_each instances, the fact that removed is a temporary declaration that can be deleted from code after apply, and that team operations should prefer declarative approaches (removed/moved).

  • Keep the real resource + unmanage it → removed
  • Keep the real resource + change its address → moved
  • Delete the real resource → destroy
  • One-off state operation → terraform state rm (not declarative)

Check Your Understanding

Pro

問題 1

A team has changed policy so that an existing audit-log S3 bucket will from now on be managed manually by the security department. The bucket must not be deleted. The bucket definition has already been removed from the Terraform code, and the current plan proposes a destroy. Which is the most appropriate action?

  1. Specify the resource address in a removed block and delete the removed block after apply
  2. Use a moved block to move the resource to a data-source address
  3. Run terraform destroy -target=aws_s3_bucket.logs and then recreate it manually
  4. Add lifecycle ignore_changes and then apply the code

正解: A

The requirement is to “take it out of Terraform management without deleting it.” removed forgets the resource from state without performing destroy, so it fits. moved is for address changes, destroy actually deletes it, and ignore_changes only ignores configuration diffs and does not remove from state.

Frequently Asked Questions

Can removed be used on data resources?

Generally, removed targets instances of managed resources. Data sources do not create real infrastructure and are not tracked in state as managed objects, so removed normally does not apply to them.

Is it okay to keep removed in the code permanently?

It is recommended to delete it once apply has completed and you have confirmed a no-op. removed is a temporary declaration for migration and does not need to stay in the code.

What happens if I write both moved and removed for the same address?

The semantics conflict. Pick either an address change (moved) or de-management (removed). If staged migration is required, first align addresses with moved, then unmanage a different resource with removed; split the plan into phases.

Check what you learned with practice questions

Practice with certification-focused question sets

無料で問題を解いてみる
Author

NicheeLab Editorial Team

NicheeLab editorial team focused on data engineering and cloud certification learning. Content is structured around practical study needs and official exam domains.


Related articles
Terraform

HCL Syntax: Terraform's Configuration Language (2026)

HCL2 fundamentals for Terraform — blocks, attributes, expres...

Terraform

Terraform Authoring & Operations Pro: Complete Guide (2026)

Tactics for the Terraform Pro exam — module authoring, works...

Terraform

Terraform Providers: Plugin Management Fundamentals (2026)

Provider mechanics — required_providers, versions, mirrors, ...

Terraform

Terraform Resource Blocks: Declarative Infra Units (2026)

Resource block fundamentals — addresses, references, common ...

Terraform

Terraform Data Sources: Read-Only External Data (2026)

Data source basics — declaration, refresh behavior, dependen...

Browse all Terraform articles (102)
© 2026 NicheeLab All rights reserved.