Skip to content
CloudOps
All prompts
AI for Terraform Difficulty: Intermediate ClaudeChatGPTCursor

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

  1. Provide ONE template at a time. Multi-stack imports get the AI confused.
  2. After conversion, run terraform fmt then terraform validate.
  3. Run terraform plan against an empty workspace — verify the plan creates the expected resource set.
  4. 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. Use user_data with the equivalent shell commands, or null_resource with local-exec provisioner.
  • Nested stacks: each becomes its own Terraform module.
  • Custom resources backed by Lambda: convert the Lambda separately, then call it via aws_lambda_invocation or treat it as a normal null_resource with 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 code
  • terraform plan against your existing CFN-managed account — should show zero changes if the conversion is faithful

Migration cheat sheet

StepCommand / Action
1. Convert templateThis prompt
2. Validate syntaxterraform fmt && terraform validate
3. Verify plan is empty (no drift)Set up state, then terraform plan
4. Detach CFN, keep resourcesAWS CLI: aws cloudformation delete-stack --retain-resources ALL ...
5. Import into Terraform stateterraform import <addr> <id> per resource
6. Re-plan, confirm emptyterraform plan should show no changes
7. Apply (no-op confirms successful import)terraform apply

Related prompts

Newsletter

Get weekly AI workflows for DevOps engineers

Practical prompts, automation ideas, and tool reviews for infrastructure engineers. One email per week. No spam.