- Avoid accidental destroy/recreate cycles when you rename or move resources in code.
- Keep state operations visible in version control and code review.
- Validate refactors using
terraform planbefore applying them.
- You renamed a resource (for example,
aws_instance.web→aws_instance.webserver). - You reorganized code (moved resources between files or into modules).
- You want Terraform to adopt existing infrastructure created outside Terraform.
- You want Terraform to stop managing a resource while leaving it running in the cloud (e.g., handing it off to another team).
terraform state mv, terraform state rm, and terraform import. Those work, but they are procedural and happen outside of configuration — making them harder to review, test, and reproduce. HashiCorp introduced a configuration-driven approach: declare moved, removed, and import blocks in Terraform configuration. Because these refactoring declarations are code, they are version-controlled, reviewable in PRs, and validated by terraform plan before being applied.

- moved — Map an old Terraform address to a new one so state is updated without destroying the underlying resource.
- removed — Remove a resource from Terraform state while leaving the resource running in-cloud.
- import — Adopt an existing resource into Terraform state by providing the target address and the provider-specific ID.
| Refactor block | When to use | Minimal example |
|---|---|---|
moved | You only changed the resource address (renamed or moved in code) | hcl\nmoved { from = aws_instance.web to = aws_instance.webserver }\n |
removed | Tell Terraform to stop managing a resource without destroying it | hcl\nremoved { from = aws_instance.production_db }\n |
import | Adopt an existing resource into Terraform control | hcl\nimport { to = aws_s3_bucket.terraform_state id = "terraform_state_bucket" }\n |
- Use
movedonly when the real resource hasn’t changed — only its address in your configuration has. fromandtoare Terraform addresses (for example,aws_instance.web, ormodule.db.aws_db_instance.main).- Add the
movedblock to your configuration and runterraform planto validate the mapping beforeterraform apply.
- A
removedblock instructs Terraform to drop the resource from state. Terraform will not try to destroy the actual resource as part of this refactor. - If you are concerned that other code changes might try to destroy the resource accidentally, add a
lifecycleblock withprevent_destroy = trueto the resource configuration before you remove it from state. Example:
- After you validate with
terraform planand are confident the resource is safe, add theremovedblock and runterraform applyto drop it from state.
If you use
prevent_destroy = true, remember to remove or update that lifecycle rule when you want normal destroy behavior again. Leaving prevent_destroy in place can block legitimate destroy operations in future runs.- Use
importwhen a resource already exists (created manually, by another tool, or in a different workspace) and you want Terraform to manage it. tois the Terraform address you will declare in your configuration.idis the provider-specific identifier (for example, an S3 bucket name or an EC2 instance ID).- After adding the
importblock and validating withterraform plan, runterraform applyto create the state entry. You still must declare the corresponding resource in your configuration with matching arguments where applicable.
- Add the refactoring block(s) to your Terraform files (under the same root that has your state).
- Run
terraform planto preview how state will change and to validate that the mapping or import works as expected. - If the plan looks correct, run
terraform applyto update the state. The actual infrastructure will remain unchanged unless you also make other configuration changes.

moved, removed, import) is the recommended, modern workflow. It makes state changes auditable, reviewable, and safer by integrating refactors into the standard plan/apply lifecycle. These techniques are practical for day-to-day Terraform management and are relevant study topics for the HashiCorp Certified: Terraform Associate 004 exam.
Further reading and references
- Terraform State Move Command
- Terraform State Remove Command
- Terraform Import Command
- Terraform: Moved and Removed Blocks (HashiCorp)