Moved blocks

Moved blocks

A moved block tells Terraform that a resource has a new address in your configuration. Without it, renaming a resource or moving it into a module makes Terraform plan to destroy the object at the old address and create a new one at the new address. A moved block updates the state instead, leaving the real infrastructure untouched.

  flowchart LR
    old["random_pet.server"] -- "moved block<br/>(state only, no destroy)" --> new["random_pet.web_server"]

Say you want to rename a resource:

main.tf
1
2
3
resource "random_pet" "server" {
  length = 2
}

Rename the resource and add a moved block with the old address in from and the new address in to:

main.tf
1
2
3
4
5
6
7
8
resource "random_pet" "web_server" {
  length = 2
}

moved {
  from = random_pet.server
  to   = random_pet.web_server
}

Terraform confirms in the plan that nothing will be recreated:

random_pet.web_server: Refreshing state... [id=neat-alpaca]

Plan: 0 to add, 0 to change, 0 to destroy.

Moved blocks also handle refactoring a resource into a module:

main.tf
1
2
3
4
moved {
  from = random_pet.web_server
  to   = module.naming.random_pet.web_server
}

…and switching from count to for_each:

main.tf
1
2
3
4
moved {
  from = random_pet.server[0]
  to   = random_pet.server["primary"]
}

Best practices

  • Add a moved block whenever you rename a resource, move it into or out of a module, or change its count/for_each keys — never let Terraform destroy and recreate an object just because of a refactoring.
  • Always check the plan says 0 to destroy after a refactoring.
  • Keep moved blocks in place for a release or two if others consume your modules, so their state migrates too — then clean them up.