Terraform (and its fork, OpenTofu) uses its own config language, HCL, and supports more clouds and services than anything else - the safe default for multi-cloud teams. Pulumi lets you write the same infrastructure in TypeScript, Python, Go, or C#, and it runs on its own engine. AWS CDK also uses those languages, but it turns your code into CloudFormation and is built for AWS.
There's no single winner here, because each tool was built for a different kind of team. So the useful question isn't "which one is better." It's "who writes this, who keeps it running in three years, and how many clouds does it need to cover?"
Start With These Questions Before Choosing an IaC Tool
Most comparisons start with syntax. That's the wrong end. Teams almost never regret the language they picked - they regret the way of working that came with it. Answer these five questions first.
1. Is AWS the whole story, or just the biggest part of it?
"We're AWS-only" is true less often than teams think. Look at what else you already run:
- Cloudflare DNS and WAF rules
- Datadog monitors and dashboards
- GitHub repos, teams, and runners
- Auth0 or Okta tenants
- Snowflake, Confluent, PagerDuty
If someone has to create those by hand today, you're already multi-provider. An AWS-only tool will eventually get a second tool bolted next to it.
2. Who keeps this running in three years?
Not who writes the first version. Who gets paged at 3 a.m. and has to read the code.
Picture your team three years from now. If it's two platform engineers who inherited everything, they need code they can read fast. If it's the same product engineers who ship the app, they need the language they already use every day.
3. Is your team closer to ops or to software engineering?
Imagine a SaaS company with five engineers. Everyone writes application code, nobody wants to switch languages just to create an S3 bucket. That team will move much faster in Pulumi or CDK.
Now imagine a team that lives in the terminal, runs everything through CI, and reviews changes by reading plans. They'll be faster in HCL, where there's basically one way to write things.
4. How complex will this actually get?
Resource count matters less than how many times you deploy the same thing across environments, regions, and tenants.Fifty resources deployed once is easy in any tool. Fifty resources deployed forty times with per-customer differences is where loops and modules start deciding your quality of life.
5. Standard building blocks, or lots of custom logic?
If most of what you deploy is VPC, EKS, RDS, S3, and IAM in familiar shapes, HCL's limits are a feature. They stop people from being clever.
If you're building an internal platform where one call should create a service with its database, queue, dashboards, alerts, and permissions, a real programming language stops being a preference and starts saving weeks.
Bottom line: pick the tool last. These five answers will already rule out one of the three options.
Where Terraform, Pulumi, and AWS CDK Take Different Paths

What you're actually writing
With Terraform or OpenTofu, you describe what you want and the tool produces a plan. That plan is the contract - anyone on the team can read it in a pull request, even people who don't write code.
With Pulumi, you write a program that builds a resource graph. You get loops, types, and unit tests, plus a preview that looks a lot like a Terraform plan. The catch: reviewing a change sometimes means reading code, not just a diff.
With AWS CDK, you also write a program, but it generates CloudFormation. That trade goes both ways:



