Terraform Refactoring · Terraform systems note

Terraform moved Blocks Are Migration History, Not Cleanup Noise

A moved block records that a resource address changed while the remote object did not. Removing it too early can make older module consumers see a destructive refactor.

Renaming a Terraform resource changes its address, even when the remote object should remain unchanged. Without migration information, Terraform can see the old address disappear and a new one appear.

moved blocks preserve object identity

moved {
  from = aws_instance.web
  to   = aws_instance.app
}

Terraform checks state for the old address, re-associates the object with the new address, then plans from there.

Migration belongs with the module

For shared modules, a moved block is better than telling every consumer to run state mv. Dev, staging and production can all upgrade through the same declared migration.

Removing it can be breaking

A workspace that skips intermediate module versions may still carry the old address. HashiCorp explicitly treats removal of moved history as a compatibility decision.

Plan the refactor like a schema migration

Review every moved instance, ensure preserved resources show address changes rather than destroy/create, and keep migration blocks until you intentionally drop compatibility with older state layouts.

Sources and further reading