OpsCanary
Back to daily brief
terraformmodulesPractitioner

Refactor Terraform Modules with Moved Blocks

4 min read HashiCorp DocsApr 27, 2026
Share
PractitionerHands-on experience recommended

Refactoring modules is essential for maintaining clean, manageable infrastructure as code. When you need to rename or move resources, the challenge lies in ensuring that existing resources remain intact. Moved blocks in Terraform provide a solution by allowing you to update resource addresses without destruction, which is critical for production environments where uptime and data integrity matter.

To use moved blocks, you need Terraform v1.1 or later. You add a moved block to your configuration, specifying the 'from' and 'to' addresses. Terraform checks the state for an existing resource at the 'from' address before creating a new plan. This means that the resource remains intact during the transition. For example, you can write a moved block like this: moved{from=aws_instance.a=aws_instance.b}. This tells Terraform to treat the resource at the old address as if it were at the new address in future plans, ensuring a seamless transition.

In production, it's vital to remember that removing a moved block is a breaking change. This can lead to unexpected behavior if not managed carefully. Additionally, you cannot use moved blocks to convert a managed resource into a data resource. Understanding these limitations will help you avoid pitfalls when refactoring your modules.

Key takeaways

  • Use moved blocks to update resource addresses without destroying existing resources.
  • Specify 'from' and 'to' addresses in moved blocks to ensure seamless transitions.
  • Remember that removing a moved block is a breaking change and can disrupt your infrastructure.

Why it matters

In production, maintaining resource integrity during refactoring is crucial. Moved blocks help prevent downtime and data loss, which can be costly.

Code examples

HCL
moved{from=aws_instance.a=aws_instance.b}
HCL
module"a"{source="../modules/example"count=3# (module arguments)}moved{from=module.a=module.a[2]}
HCL
resource"aws_instance""a"{count=2# (resource-type-specific configuration)}moved{from=aws_instance.a=aws_instance.a["small"]}

When NOT to use this

The official docs don't call out specific anti-patterns here. Use your judgment based on your scale and requirements.

Want the complete reference?

Read official docs

Test what you just learned

Quiz questions written from this article

Take the quiz →

Get the daily digest

One email. 5 articles. Every morning.

No spam. Unsubscribe anytime.