Terraform Migration Playbooks
Five dedicated playbooks for safely migrating Terraform resources without causing identity churn, data loss, or downtime.
Playbook 1: count to for_each Migration
Goal: Keep object identity stable during refactor.
Steps
- Define stable keys (not list indexes)
- Add
for_eachimplementation - Add
movedmappings from old index addresses to new keyed addresses - Run plan and confirm move operations (not destroy/create)
- Apply in low-risk environment first
Example Mapping
moved {
from = aws_subnet.app[0]
to = aws_subnet.app["a"]
}
moved {
from = aws_subnet.app[1]
to = aws_subnet.app["b"]
}
Playbook 2: Resource/Module Rename
Use moved for address renames before any apply.
moved {
from = module.edge_cache
to = module.cdn_edge
}
Playbook 3: Import-First Adoption
When taking over manually created resources:
- Confirm remote object exactly matches intended config shape
- Import into correct address
- Run plan and ensure no surprise replacements
Declarative import Block (TF 1.5+ / OpenTofu 1.5+)
Prefer declarative import blocks over CLI terraform import:
import {
to = aws_s3_bucket.logs
id = "my-existing-bucket-name"
}
resource "aws_s3_bucket" "logs" {
bucket = "my-existing-bucket-name"
}
Bulk Import with for_each
locals {
existing_buckets = {
logs = "prod-logs-bucket"
archive = "prod-archive-bucket"
}
}
import {
for_each = local.existing_buckets
to = aws_s3_bucket.managed[each.key]
id = each.value
}
resource "aws_s3_bucket" "managed" {
for_each = local.existing_buckets
bucket = each.value
}
Post-Import Checklist
- Run
terraform planand verify zero changes (no-diff) - If plan shows changes, align config with actual state before applying
- Remove
importblocks after successful apply (they are one-time directives)
Playbook 4: Secrets Remediation
If secrets are currently in state:
- Create new secret path in managed secret store
- Switch resources to reference external secret material
- Rotate credentials after cutover
- Remove old secret-generating Terraform resources where possible
Playbook 5: Runtime/Provider Upgrade Flow
- Bump constraints intentionally
- Regenerate lockfile
- Run full test tier for target risk
- Inspect deprecations and behavior shifts
- Ship upgrade independently from functional changes when possible
Migration Red Flags
Watch for these warning signs during any migration:
- Plan shows broad replace for unrelated resources
- Key changes derived from unstable list order
- Unknown ownership of imported resources
- No rollback narrative for production apply