CloudFormation to Terraform Blueprint
This blueprint migrates AWS CloudFormation stacks to Terraform without recreating resources. It uses retain policies, careful state import, an expand-and-contract coexistence period, and dependency-ordered cutover to keep stateful resources intact.
What and Why
AWS CloudFormation is Amazon's native IaC service; templates describe stacks and CloudFormation manages their lifecycle. Teams move to Terraform for multi-cloud consistency, a richer module ecosystem, faster plan feedback, and HCL's expressiveness over verbose JSON/YAML templates and intrinsic functions. The core challenge is that both tools want to own the same resources, so the migration must avoid recreation and downtime, especially for stateful resources.
This is not a rewrite-and-redeploy exercise. Done carelessly it will replace databases and load balancers; done carefully it moves ownership of live resources from one tool to another with zero recreation.
Phases
Assessment. Inventory all stacks, nested stacks, cross-stack exports/imports, and custom resources backed by Lambda. Identify stateful resources (RDS, S3, DynamoDB, EFS) that must never be recreated, and intrinsic functions (Fn::GetAtt, Fn::ImportValue) that have no direct Terraform analog. Map the dependency graph between stacks so migration order can avoid breaking exports.
Design. Choose a Terraform backend with locking, an account/workspace layout, and a module structure that mirrors the existing stack boundaries to ease the move. Decide migration order: leaf stacks with no exports first, shared/networking stacks last. Plan how cross-stack outputs become Terraform data sources or terraform_remote_state references. Define secret handling via Vault or AWS Secrets Manager so nothing sensitive lands in HCL or state.
Coexistence. Establish a period where CloudFormation and Terraform run side by side. Use an expand-and-contract approach: set DeletionPolicy: Retain (and UpdateReplacePolicy: Retain) on resources, remove them from the CloudFormation stack so the stack no longer manages them but the resources survive, and then bring them into Terraform. Tools such as cf2tf or terraformer can scaffold HCL, but every generated file must be reviewed against the real resource.
Import. For each resource removed from CloudFormation with a retain policy, import it into Terraform (terraform import or import blocks) and write HCL until terraform plan is clean. Confirm tags, policies, parameters, and encryption settings match exactly so no replacement is proposed. Use prevent_destroy on stateful resources as a safety net.
Cutover. Once a stack's resources are fully managed by Terraform, delete the now-empty CloudFormation stack. Move CI/CD to Terraform plan-on-PR and apply-on-merge with OIDC-federated credentials, add policy-as-code, and enable scheduled drift detection. Repeat per stack until CloudFormation is retired.
Key Risks and Mitigations
- Resource recreation. A mismatched attribute can force replacement of a database or bucket. Always set retain policies before removal, import carefully, require a no-op plan before apply, and use
prevent_destroy. - State drift. Use a remote locking backend, enable state bucket versioning, never hand-edit state, and run scheduled drift checks.
- Cross-stack dependencies. Exports/imports break if migrated out of order. Map the dependency graph, migrate leaf stacks first, and replace exports with data sources or remote state lookups.
Recommended Tooling
Terraform or OpenTofu, a locking remote backend (S3 plus DynamoDB or a managed backend), scaffolding helpers (terraformer/cf2tf) used only with review, policy-as-code (Conftest/OPA or Sentinel), Vault or AWS Secrets Manager, and CI/CD for gated plan/apply.
Success Metrics
Track provisioning lead time, infrastructure-under-Terraform percentage, drift incidents, and change failure rate. Zero unplanned recreations of stateful resources is the headline safety metric.
Prerequisites
A full stack and dependency inventory, retain policies applied to stateful resources, a remote state backend, scoped IAM roles, and CI/CD capable of gated Terraform runs. Before the first import, take a backup or snapshot of stateful resources and confirm the team can read CloudFormation drift detection output, since resources that already drifted from their templates need reconciling first. Agree on a rollback plan for each wave, and run the import and plan steps in a non-production account to rehearse the procedure before touching production stacks.