AWS CDK vs Terraform for Existing AWS Stacks

Close-up of a monitor showing colorful programming code in a dark editor

Photo by Ilya Pavlov on Unsplash

AWS CDK vs Terraform for existing AWS stacks comes down to who owns state. CDK deploys through CloudFormation, so a CloudFormation stack can move to CDK with cdk migrate and keep its stack and resources. Terraform keeps its own state file, so moving there means retaining, releasing and importing every resource. If your stacks work and your team knows the tool, don’t migrate.

Most CDK vs Terraform comparisons assume a blank account. This one is for teams whose AWS infrastructure already exists, usually as hand-written CloudFormation, a few CDK apps, some Terraform, and resources someone created in the console. The question isn’t which tool is better in the abstract. It’s what it costs to move what you already run, and what you get for it.

You’ll get a side-by-side comparison of AWS CDK vs Terraform for existing AWS stacks, the migration path in each direction with the real commands, and a clear list of reasons to stay put.

How AWS CDK vs Terraform state management differs

Everything else follows from this. CDK has no state of its own. cdk synth produces a CloudFormation template, and cdk deploy hands it to CloudFormation, which records what exists in the stack. You can open the stack in the CloudFormation console and see every resource, whether a human or CDK wrote the template.

Terraform owns its state. It writes a state file that maps each resource address to a real resource ID, usually in an S3 backend with locking. CloudFormation knows nothing about resources Terraform manages, and Terraform knows nothing about stacks.

So for an existing CloudFormation estate, CDK is a change of authoring language on the same engine, while Terraform is a change of engine. The first can be done stack by stack without moving a single resource. The second moves every resource from one owner to another, which is what our walkthrough to import CloudFormation resources into Terraform safely covers step by step.

Side-by-side comparison for existing AWS infrastructure

Question AWS CDK Terraform
Where state lives CloudFormation stacks in your account Terraform state file in a backend you run (S3, Terraform Cloud)
Adopting a CloudFormation stack cdk migrate --from-stack keeps the stack name and logical IDs Retain resources, release them from the stack, then import blocks
Adopting unmanaged resources cdk import or cdk migrate --from-scan import blocks with terraform plan -generate-config-out
Preview before deploy cdk diff and CloudFormation change sets terraform plan
Failed deploy CloudFormation rolls the stack back by default No automatic rollback; the partial apply stays and you fix forward
Language TypeScript, Python, Java, C#, Go HCL
Clouds and SaaS AWS only AWS plus other clouds and SaaS providers
Stack size limits CloudFormation’s per-stack resource quota applies (500) No stack concept; large states get slow to plan

Moving existing CloudFormation stacks to CDK

cdk migrate reads a deployed stack, a local template or scanned resources and writes a new CDK app with a single stack. The AWS guide to migrating existing resources and CloudFormation templates to the AWS CDK lists the rules, and three matter most. The feature is in preview. It generates L1 constructs only (one-to-one with CloudFormation resource types). And it doesn’t support nested templates.

Terminal

cdk migrate --from-stack --stack-name "orders-data" --language typescript
cd orders-data
npm install
cdk synth
cdk diff

Because the stack name and logical IDs match, the first cdk deploy is an ordinary stack update, not a create. Run cdk diff first and expect no resource replacements. Lambda code and other assets don’t migrate automatically; you point the app at them afterward.

For a resource that exists outside any stack, write the construct yourself and run cdk import. The only change allowed in that deploy is the new resource, and you must model its current settings exactly:

lib/orders-archive-stack.ts

import * as cdk from "aws-cdk-lib";
import * as s3 from "aws-cdk-lib/aws-s3";
import { Construct } from "constructs";

export class OrdersArchiveStack extends cdk.Stack {
  constructor(scope: Construct, id: string, props?: cdk.StackProps) {
    super(scope, id, props);

    new s3.Bucket(this, "OrdersArchiveBucket", {
      bucketName: "acme-orders-archive-123456789012",
      versioned: true,
      blockPublicAccess: s3.BlockPublicAccess.BLOCK_ALL,
      removalPolicy: cdk.RemovalPolicy.RETAIN,
    });
  }
}

const app = new cdk.App();
new OrdersArchiveStack(app, "OrdersArchiveStack");
Terminal

cdk diff OrdersArchiveStack
cdk import OrdersArchiveStack

cdk import prompts for the physical name of each new resource. For CI, record the answers once with --record-resource-mapping mapping.json and replay them with --resource-mapping mapping.json.

Terraform to AWS CDK migration considerations

Going from Terraform to CDK is the expensive direction, because resources change owner. Our guide to migrate a Terraform stack to AWS CDK TypeScript has every command; the sequence:

  1. Translate the configurationDraft CDK code from HCL with the free Terraform to CDK TypeScript converter or the Terraform to CDK Python converter, then set RemovalPolicy.RETAIN on stateful resources.
  2. Release from Terraform without destroyingOn Terraform 1.7 or later, add a removed block with destroy = false and apply. The resource leaves state and stays in AWS.
  3. Import into CDKRun cdk import for the stack. Resources that reference each other must be imported together or in dependency order.
  4. Check for driftRun CloudFormation drift detection on the new stack, since cdk import doesn’t verify that your properties match the live resource. To check every stack in the account later, use the script to detect CloudFormation drift across all stacks.
release.tf

removed {
  from = aws_s3_bucket.orders_archive

  lifecycle {
    destroy = false
  }
}

The reverse trip, CDK to Terraform, mirrors the CloudFormation-to-Terraform procedure: set RemovalPolicy.RETAIN, deploy, remove the constructs or destroy the stack, then import with Terraform. The AWS CDK to Terraform converter gives you the starting HCL.

When to migrate from Terraform to CDK (or the other way)

Choose AWS CDK if…

  • Your existing estate is mostly CloudFormation. cdk migrate changes the language without moving resources.
  • Your infrastructure is AWS only and likely to stay that way.
  • Your team writes TypeScript or Python daily and wants loops, types, tests and shared libraries in the same language as the application.
  • You want CloudFormation’s automatic rollback on failed deploys.

Choose Terraform if…

  • You manage more than AWS: DNS at another provider, a second cloud, SaaS tools like monitoring or identity.
  • Your team already reads HCL and has plan-review habits in pull requests.
  • You want one state model across every account and provider rather than hundreds of CloudFormation stacks.
  • Stacks keep hitting CloudFormation limits or slow rollbacks block deploys.

Don’t migrate if…

  • The stacks deploy reliably and the only argument is preference. A migration touches every stateful resource and buys you nothing users can see.
  • Nobody on the team can own the new tool for the next year.
  • You’d be migrating to escape a specific pain, like verbose YAML, that a smaller change fixes. CDK on top of existing templates, or Terraform modules for new work only, are both valid.

CDK or Terraform for AWS-only infrastructure?

For AWS-only work, both tools cover the services you’re likely to use, and the deciding factors are people and state, not features. Pick the tool the people who’ll be paged at 2 a.m. already understand. A mixed estate is fine: many teams keep legacy CloudFormation or CDK for what exists and write new services in Terraform, or the reverse. The rule is one owner per resource, never two. Pulumi is a third option with its own state, and the steps to migrate a Terraform stack to Pulumi TypeScript follow the same import-then-release order.

If you’re still learning what’s actually deployed before deciding, it helps to list AWS resources in plain English from the terminal first, so the migration plan is based on the real inventory, not the Git repository.

Common mistakes when switching tools

  • Deploying before diffing. A renamed logical ID in CDK means delete-and-create. Always read cdk diff or terraform plan for replacements first.
  • Two owners for one resource. Terraform and CloudFormation will overwrite each other’s changes without warning.
  • Trusting converted code blindly. Converters and cdk migrate output are drafts. Converted code is a starting point that must be reviewed and tested; the free converters mark untranslatable parts in comments.
  • Forgetting the IAM side. The CDK bootstrap roles and a Terraform CI role need different permissions. Review each with our checklist to review a generated IAM policy for least privilege.

After a migration, if something behaves differently than before, the approach in troubleshooting AWS infrastructure with an AI CLI helps you compare live state with what you expected.

What ChatWithCloud can and can’t do here

The 19 free AI converters for SDK and IaC code draft code in either direction, including CDK TypeScript to Python with the CDK TypeScript to Python converter; the steps to translate an AWS CDK TypeScript app to Python keep logical IDs stable. They don’t read your account, touch your state, or run cdk or terraform. Before pasting infrastructure code, read what happens when you paste AWS code into an AI converter, and check the ChatWithCloud converter rate limits and size caps before a large batch. The ChatWithCloud CLI use cases page covers the separate command-line tool, which answers questions about your account with your own AWS profile.

Frequently asked questions

Does AWS CDK use Terraform state?

No. CDK deploys through CloudFormation, which tracks resources in stacks. Terraform state files aren’t involved.

Can cdk migrate convert a Terraform project?

No. Its sources are deployed CloudFormation stacks, local CloudFormation templates and scanned resources. For Terraform, translate the HCL, release resources from state, then use cdk import.

Is Terraform better than CDK for multi-account AWS?

Both handle many accounts. Terraform uses provider aliases or workspaces; CDK sets an account and region per stack and deploys each one to its environment. Team familiarity matters more than the tool.

Can I run CDK and Terraform in the same AWS account?

Yes, as long as each resource has exactly one owner. Pass values between them through SSM parameters or data sources, not by managing the same resource twice.

Related guides

Ask your AWS account in plain English

Your first 15 runs are free, with no OpenAI key needed.

npx chatwithcloud