When you rename a Terraform resource or move it into a module, Terraform sees the old address vanish and a new one appear, and plans to destroy and recreate it. A moved block tells Terraform to rename the object in state first, so nothing is destroyed. Use it for any refactor that touches stateful resources.
The problem
Terraform tracks resources by address, such as aws_db_instance.main. Rename that to aws_db_instance.primary and, to Terraform, the first is gone from the configuration and the second is new. The plan shows one destroy and one create. For a stateless resource that is a nuisance. For a database, a key or a bucket it can be data loss.
What a moved block does
HashiCorp's documentation says the block is used to programmatically change the address of a resource. Terraform checks state for an object at the from address and renames it to the to address before planning. As a result, Terraform does not destroy the resource during that run.
moved {
from = aws_db_instance.main
to = aws_db_instance.primary
}
The page I fetched points to a separate refactoring page for fuller usage, so check that guide for module moves and edge cases.
A safe refactoring routine
- Make the rename in code and add the moved block in the same change.
- Run a plan and read the summary. You want zero destroys, with the move noted.
- If the plan still shows destroy and create, stop. The addresses probably do not match.
- Apply, and confirm state shows the new address.
- Keep the moved block for a while so other copies of the configuration, such as other environments, also migrate.
Why this is a security topic
Accidental recreation of security-relevant resources causes real incidents:
- A recreated key store can orphan encrypted data.
- A recreated bucket loses its policy and public access settings until the next apply restores them.
- A recreated database loses its data, or comes up with new defaults.
- A recreated identity role can break trust relationships briefly or permanently.
Reading the plan for any destroy on stateful resources is the review step that prevents most of these. Pair it with lifecycle protections and backups, since protections like prevent_destroy depend on the block staying in the configuration.
Reviewer notes
- A pull request that renames resources should include moved blocks and a plan showing no destroys.
- Treat a rename without a moved block as suspicious, especially for stateful types.
- Never approve a plan you did not read because the diff looked cosmetic.
Safeguard's policies and gates can require checks on pull requests that touch infrastructure files, such as a named approver for destroy actions you configure.
Quick check
What happens if I rename a resource and add no moved block?
Terraform plans to destroy the old address and create the new one, which can mean losing data on stateful resources.
Can I remove a moved block after applying?
Often, once every state that needs migrating has applied it. Keep it while other environments or copies still use the old address.
Sources
Last reviewed: 19 October 2026.