CloudFormation to Terraform Conversion Prompt
Convert an AWS CloudFormation template (YAML or JSON) into idiomatic Terraform HCL — preserving behavior, improving readability.
- Target user
- AWS engineers migrating from CloudFormation to Terraform
- Difficulty
- Intermediate
- Tools
- Claude, ChatGPT, Cursor
The prompt
You are a senior AWS infrastructure engineer with deep experience in both CloudFormation and Terraform. You've migrated dozens of templates from CFN to TF and know where the resource mappings get subtle.
Convert the CloudFormation template I share into Terraform HCL. Rules:
1. **Preserve behavior first, improve idiomaticness second.** The Terraform output should provision the same AWS resources with the same configuration. Don't silently change defaults.
2. **Map resources correctly.** Use `aws_*` resources from the AWS provider. If a CFN resource has no direct TF equivalent (e.g., `AWS::CloudFormation::CustomResource`), call it out and propose an alternative (Lambda + null_resource, or a real AWS resource).
3. **Convert intrinsic functions:**
- `!Ref param` → `var.param` (if it's a parameter) or `aws_resource.name.id` (if it's a resource)
- `!GetAtt resource.attr` → `aws_resource.name.attr`
- `!Sub` → string interpolation `"${...}"`
- `!Join` → `join()` or string interpolation
- `!If condition value1 value2` → conditional expression `condition ? value1 : value2`
- `!FindInMap` → local map lookup
4. **Parameters → variables.** Add `type`, `description`, and `default`. Convert `AllowedValues` to a `validation` block.
5. **Outputs.** Map CFN `Outputs` to Terraform `output` blocks with descriptions.
6. **Mappings → locals.** Convert `Mappings` to `locals { ... }` with the same lookup pattern.
7. **Conditions.** Convert CFN `Conditions` to Terraform `count` or `for_each` patterns on the relevant resources.
8. **File layout.** Produce: `variables.tf`, `main.tf`, `outputs.tf`, `versions.tf` (with required_providers).
After conversion, list:
- Any CFN features that did NOT translate cleanly and need manual review
- Any AWS defaults that differ between CFN and the AWS provider (e.g., default tags, encryption defaults)
- Suggested next steps (state import, module extraction, testing)
CloudFormation template:
```yaml
[PASTE]
```
Target AWS provider version: [e.g. ~> 5.0]
Terraform version: [e.g. >= 1.6]
Why this prompt works
CFN-to-TF conversion goes wrong in two predictable ways: people use auto-converters that produce non-idiomatic mush, or they hand-port and miss the intrinsic functions. This prompt anchors the conversion in the actual mapping rules and forces the AI to flag what didn’t translate.
How to use it
- Provide ONE template at a time. Multi-stack imports get the AI confused.
- After conversion, run
terraform fmtthenterraform validate. - Run
terraform planagainst an empty workspace — verify the plan creates the expected resource set. - To take over an existing CFN-managed stack: see the migration pattern in the safety notes above.
What gets tricky
AWS::CloudFormation::Init(cfn-init): doesn’t map directly. Useuser_datawith the equivalent shell commands, ornull_resourcewithlocal-execprovisioner.- Nested stacks: each becomes its own Terraform module.
- Custom resources backed by Lambda: convert the Lambda separately, then call it via
aws_lambda_invocationor treat it as a normalnull_resourcewith a Lambda invoke. - DeletionPolicy: Retain: must become
lifecycle { prevent_destroy = true }in Terraform. - UpdateReplacePolicy: Retain: requires
lifecycle { ignore_changes = [...] }for the relevant fields.
Pair this with
cf2tf— programmatic CFN-to-Terraform converter (use as a sanity check)terraformer— reverse-engineer existing AWS resources into Terraform codeterraform planagainst your existing CFN-managed account — should show zero changes if the conversion is faithful
Migration cheat sheet
| Step | Command / Action |
|---|---|
| 1. Convert template | This prompt |
| 2. Validate syntax | terraform fmt && terraform validate |
| 3. Verify plan is empty (no drift) | Set up state, then terraform plan |
| 4. Detach CFN, keep resources | AWS CLI: aws cloudformation delete-stack --retain-resources ALL ... |
| 5. Import into Terraform state | terraform import <addr> <id> per resource |
| 6. Re-plan, confirm empty | terraform plan should show no changes |
| 7. Apply (no-op confirms successful import) | terraform apply |
Related prompts
-
Infrastructure as Code Security Review Prompt
AI security review of Terraform, CloudFormation, or Helm charts — surface dangerous defaults, missing encryption, overly-permissive IAM, and exposed services.
-
Dangerous Terraform Changes Review Prompt
Scan a `terraform plan` output for changes that will silently destroy data, cause outages, or trigger irreversible mutations.
-
Terraform Module Review Prompt
Get a senior-engineer review of a Terraform module — variable hygiene, state safety, security defaults, drift resistance.