terraform state rm removes a resource from state and stops Terraform from managing it. The actual infrastructure is not deleted, but the behavior of the next plan/apply changes significantly.
This guide walks through the safe production procedure, common scenarios, address-targeting tips, and how state rm differs from destroy, state mv, moved, and import — all aligned with the official Terraform documentation.
terraform state rm removes the specified resource instance from the current Terraform state. The real infrastructure is not destroyed. Terraform then treats that resource as unmanaged, and if the same address still exists in HCL, the next plan will propose creating it again.
The main use cases are: (1) handing an existing resource off to manual operation, (2) cleaning up stale state for a resource that was deleted by hand, and (3) temporarily removing a resource before a module reorganization or rename. If your goal is a rename or move, state mv or a moved block is safer and more reproducible.
Basic operation template
terraform state list
# => check the addresses currently under management
terraform state show aws_s3_bucket.logs
# => inspect the state details
terraform state rm aws_s3_bucket.logs
# => remove from state (the bucket itself remains)state rm is a powerful operation. To apply it safely, you need a backup, an impact assessment, and HCL-side consistency adjustments. In particular, running state rm while the HCL definition is still present will produce a "create" diff on the next plan and can lead to unintended duplicate creation.
The recommended production sequence is below. If the backend supports locking (S3 + DynamoDB lock, Terraform Cloud/Enterprise, etc.), the lock kicks in automatically, but make absolutely sure no parallel apply is running.
Example execution (Bash)
# 1) Back up state
terraform state pull > tfstate-$(date +%F-%H%M%S).bak
# 2) Identify the target address
terraform state list | grep aws_s3_bucket
terraform state show aws_s3_bucket.logs
# 3) Comment out/delete the resource from HCL (commit to VCS)
# 4) Sync the current state if needed
terraform plan -refresh-only
# 5) Remove from state
terraform state rm aws_s3_bucket.logs
# 6) Confirm the diff matches your intent
terraform planCleaning up after a manual delete: if the real infrastructure was deleted manually, delete the matching resource from HCL as well, and finally use state rm to clean up the leftover state entry. Running rm while HCL still defines the resource will trigger recreation, which contradicts the goal.
Handing off select resources to manual operation: remove the HCL definition or exclude it via a conditional (e.g., count=0) and then run state rm. Verify that future applies will not recreate the resource.
Module reorganization or renames: use a moved block or state mv as a rule and avoid rm. If you must remove a resource, plan the re-import up front.
Precise addressing for for_each and module-nested resources
# for_each keys must be quoted
terraform state rm 'aws_subnet.public["public-1a"]'
# A specific instance inside a module
terraform state rm 'module.network.aws_subnet.public["public-1a"]'
# Check the current workspace
terraform workspace showRight after state rm, if the same resource definition remains in HCL, Terraform concludes "not in state = not yet created." The plan proposes a create, and the apply can produce duplicate creation or naming-collision errors.
Dependencies are largely rebuilt from HCL, so rm rarely breaks dependency resolution. However, if outputs or referencing resources point to something that no longer exists in state, you can hit errors or unknown-value propagation.
The world after state rm (conceptual flow)
Example of unintended recreation
# resource "aws_s3_bucket" "logs" is still defined in HCL
terraform state rm aws_s3_bucket.logs
terraform plan
# => + create aws_s3_bucket.logs (possible duplicate creation / naming collision)Addresses follow resource.type.name[index or key], and module-nested resources use module.path.resource.... A mistyped address can remove the wrong thing, so always confirm with terraform state list / show.
For renames or module moves, Terraform 1.1+ recommends declarative state migration with a moved block. At plan time the state is migrated automatically from the old address to the new one, which is reproducible and avoids the orphaning risk of rm.
Syntax examples: moved block, state mv, import
# moved (HCL, Terraform 1.1+)
moved {
from = aws_s3_bucket.logs
to = module.logging.aws_s3_bucket.logs
}
# state mv (CLI)
terraform state mv aws_s3_bucket.logs module.logging.aws_s3_bucket.logs
# Reattach an existing resource (import)
terraform import aws_s3_bucket.logs my-logs-bucket-nameThe Pro exam frequently asks you to distinguish between "untrack without destroying," "what to use for a rename," and "reattaching an existing resource." state rm only stops managing the resource, destroy actually destroys it, state mv / moved migrate state, and import brings an existing resource into state.
For refresh-related operations, apply -refresh-only is the current recommendation. -target is an emergency tool for minimization, not a recommended practice for normal operations.
| Command / Feature | Effect on Real Infrastructure | Effect on State | Main Use Case |
|---|---|---|---|
| terraform state rm | No deletion (does not destroy) | Removes the specified address | Untrack a resource, clean up stale entries |
| terraform destroy (including -target) | Destroys the real resource | Removed as part of destruction | Explicit teardown; targeted destruction is for emergencies only |
| terraform state mv / moved{} | Does not destroy | Moves from the old address to the new one | Renames and module migrations |
| terraform import | Does not destroy | Registers an existing resource | Adopting hand-built assets |
| terraform apply -refresh-only | Does not destroy | Updates attributes via reads | State sync and drift detection |
One-liners that often appear on the exam
# "Untrack without destroying":
terraform state rm module.db.aws_db_instance.main
# "Rename / relocate":
terraform state mv aws_iam_role.app module.iam.aws_iam_role.app
# or declaratively with a moved block in HCL
# "Adopt an existing resource":
terraform import aws_eip.web eipalloc-1234567890abcdef0Pro
問題 1
You want to operate an existing S3 bucket manually going forward. Terraform must stop managing the bucket, and the real bucket must not be deleted. Which procedure is correct?
正解: A
To untrack without destroying, the correct move is to delete the HCL definition (or disable its creation condition) and also remove it from state via state rm. D triggers recreation on the next plan, B destroys the real resource, and C is move/reattach, which does not match the requirement.
I removed something with state rm by mistake. How do I get it back?
The safest option is to restore from a backed-up tfstate (use terraform state push carefully). If you have no backup but the underlying resource still exists in the cloud, prepare the matching HCL and reattach it with terraform import.
Do I need any special flags with a remote backend? What about locking?
Generally no extra flags are needed. If the backend supports locking (S3 + DynamoDB, Terraform Cloud/Enterprise, etc.), state rm honors the lock just like plan/apply. Avoid concurrent operations such as running apply in another terminal.
Can data sources also be targeted by state rm?
Data sources can appear in state but are re-read at plan time, so you usually don't need to rm them. Only do so when truly necessary, and only after confirming the address carefully.
Practice with certification-focused question sets
無料で問題を解いてみる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.
HCL Syntax: Terraform's Configuration Language (2026)
HCL2 fundamentals for Terraform — blocks, attributes, expres...
Terraform Authoring & Operations Pro: Complete Guide (2026)
Tactics for the Terraform Pro exam — module authoring, works...
Terraform Providers: Plugin Management Fundamentals (2026)
Provider mechanics — required_providers, versions, mirrors, ...
Terraform Resource Blocks: Declarative Infra Units (2026)
Resource block fundamentals — addresses, references, common ...
Terraform Data Sources: Read-Only External Data (2026)
Data source basics — declaration, refresh behavior, dependen...