Pulumi vs. Terraform vs. AWS CDK: Which IaC Tool to Choose?

Do you have an interesting IT project in mind? Don’t skip the discovery phase. Learn more about it in our article.

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

IaC tools comparison diagram

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:

CloudFormation gives youCloudFormation charges you

No state file to lose or corrupt

Slow deploys on big stacks

Drift detection handled by AWS

Rough rollbacks when an update fails

Automatic rollback behavior

Resource limits per stack

Nothing to host yourself

New AWS features arrive later than in providers

Remember: CloudFormation owns the deployment lifecycle, not your CDK code.

That ownership has a sharp edge. Renaming a construct in your code changes its CloudFormation logical ID, and CloudFormation reads that as "delete the old resource, create a new one." Do it to a database or a bucket with data in it and the data goes with it. A rename in the editor is not a rename in AWS.

AWS-first vs. multi-cloud

CDK is built for AWS on purpose, and that focus is why its abstractions are so good. L2 and L3 constructs carry real AWS opinions - sane defaults, IAM wiring, security groups - so a load-balanced Fargate service takes a few lines instead of a few hundred. Terraform and Pulumi reach everything else: other clouds, SaaS tools, Kubernetes, databases, internal APIs.

You can manage non-AWS resources from CDK through custom resources backed by Lambda. It works, and plenty of teams do it for one or two small things. But you're writing and maintaining the integration yourself, while Terraform and Pulumi hand you a tested provider.

CDK for Terraform (CDKTF) used to be the obvious middle path - CDK-style code, Terraform providers underneath.

Worth knowing before you Google it: HashiCorp shut CDKTF down on December 10, 2025 and archived the repo, saying it never found real traction. Plenty of blog posts still recommend it. Teams that standardized on it are now moving to plain HCL or AWS CDK.

Developer experience in the age of AI-assisted infrastructure

All three have an AI story now: Terraform ships an MCP server, Pulumi has Neo as an agent that plans changes and opens PRs, AWS publishes an IaC MCP server for CDK.

Don't pick a tool for this. What changed is review. When a model writes 400 lines of infrastructure code in ten seconds, the slow part is the human deciding whether it's safe to apply.

Our take: AI changes how fast you write IaC, not how carefully you should review it.

Reusing code across teams

IaC module reuse diagram

Terraform modules are versioned, published to a registry, and deliberately simple. That's why they spread so well across large organizations, and why the public module ecosystem is still the largest of the three.

Pulumi components and CDK constructs are classes instead - inheritance, composition, npm or PyPI. CDK Mixins are now stable, which makes it much easier to apply the same rules everywhere: tagging, encryption defaults, log retention.

A detail almost nobody expects: Pulumi can run Terraform modules directly, using pulumi package add terraform-module. Under the hood it drives OpenTofu to execute them. So your investment in terraform-aws-modules isn't lost if you switch. Expect some friction on complex modules - heavy dynamic blocks and exotic HCL functions can confuse type generation - but for common modules it just works.

Scaling to a big setup

Past a few hundred resources, the real question becomes how much one mistake can break.

  • Terraform Stacks (on HCP Terraform) run dependent configs together and can postpone changes when values aren't known yet - exactly what Kubernetes needs, since the cluster has to exist before anything inside it can be planned.
  • Open-source Terraform and OpenTofu get there with Terragrunt, Terramate, or plain CI scripts.
  • Pulumi splits by project and stack; CDK splits by stack and stage, with CDK Pipelines handling order.

Ecosystem and vendor risk

This is where the landscape has shifted most since the last time you probably compared these tools.

Terraform belongs to IBM now and ships under the BSL license. OpenTofu sits at the Linux Foundation with CNCF backing, holds roughly 12% adoption among practitioners, and has shipped things Terraform's CLI doesn't have - encrypted state files being the big one. Plenty of large companies now run both: Terraform for older systems tied to HCP, OpenTofu for everything new.

Check this before you plan a migration: moving from Terraform to OpenTofu is mostly a binary swap, but it's close to one-way. Once you apply with OpenTofu 1.7+ and enable its own features, plain Terraform may no longer read your state. Take a clean backup first.

Money matters too. HCP Terraform's old free plan is gone, and the current free tier stops at 500 managed resources, with per-resource pricing above that. Pulumi's engine is open source, but the collaboration features live in Pulumi Cloud - one vendor, one control plane. CDK is free and owned by AWS, and the price is living with CloudFormation.

CriterionTerraform / OpenTofuPulumiAWS CDK

Built for

Platform and DevOps teams

Engineers who own their infra

AWS-focused product teams

Cloud reach

Any cloud + SaaS

Any cloud + SaaS + Kubernetes

AWS, plus custom resources

Engine and state

Own engine, state you manage

Own engine, Pulumi Cloud or self-hosted

CloudFormation handles it

Reuse

Registry modules

Typed components

Constructs (L1–L3), Mixins

Reviewing changes

Plan diff anyone can read

Preview plus code review

Synth diff; big changes can hide

Main risk

BSL license, IBM ownership

One vendor for the control plane

CloudFormation limits, AWS lock-in

Ramp-up for non-developers

Low

Medium-high

Medium-high

Already using one of them? Then the honest answer is usually: stay. Migrations cost months of senior engineering time, and "the other tool is nicer" is not a business case. Move only when something concrete is blocking you - a licensing rule you can't meet, a cloud your current tool can't reach, or CloudFormation limits you keep hitting. Otherwise, spend that time on modules, policies, and pipelines. You'll get more out of it.

Bottom line: Terraform optimizes for readability, Pulumi for expressiveness, CDK for speed inside AWS. Everything else follows from that.

Real-World Scenarios: Which Tool Would You Choose?

IaC tool comparison infographic

AWS-only SaaS, small team, shipping weekly

Choose AWS CDK. Constructs remove a huge amount of boilerplate, your engineers stay in TypeScript, and you never think about state files.

Trade-off: failed rollbacks will test your patience, and adding a second cloud later means a second tool or a rewrite.

Multi-cloud company with compliance requirements

Choose Terraform or OpenTofu. Provider coverage, policy as code, audit trails, and the number of people who already know it all point the same way.

The harder call isn't Terraform vs. Pulumi. It's Terraform vs. OpenTofu - and that one belongs to legal and procurement as much as to engineering.

Trade-off: when HCL runs out of road, you'll be writing generators or adding Terragrunt.

A Kubernetes platform used by many internal teams

Choose Pulumi in most cases. Building a platform is closer to product work than to scripting: golden paths, typed components, tests, self-service.

But the bigger architectural decision isn't the tool. It's the line between two systems:

  • IaC creates the cluster and everything it depends on - VPC, IAM/IRSA, node groups, databases, DNS.
  • GitOps (Argo CD or Flux) delivers everything running inside the cluster.

Once provisioning and delivery are cleanly separated, scaling a Kubernetes platform becomes far more predictable - a new cluster or a new team stops being a project and becomes a repeatable step. When that line is blurry, plans get slow, drift becomes permanent, and every deployment is harder to reason about. If you're drawing this architecture for the first time, an outside review through Kubernetes consulting can catch the decisions that are expensive to undo later.

Trade-off: two systems and two mental models, with a clear contract between them.

A team of software engineers with no dedicated DevOps

Choose Pulumi if you're multi-cloud, CDK if you're AWS-only. Either way, everyone stays in one language.

Trade-off: infrastructure code needs the same discipline as app code. The usual failure is over-abstraction - an elegant class hierarchy nobody can debug at 2 a.m.

A large DevOps organization, hundreds of engineers

Choose Terraform or OpenTofu as the base layer. Wrap it in approved modules and policy as code, then let product teams use CDK or Pulumi inside the boundaries you set.

Trade-off: governance work, and a platform team that treats its modules like a product - versions, changelogs, deprecation notices.

In practice: the tool follows the ownership model. Decide who owns infrastructure first, and the shortlist writes itself.

If this describes youChooseWhy

AWS-only, small team, need speed now

AWS CDK

Best AWS abstractions, no state to manage

Multi-cloud or lots of SaaS to provision

Terraform / OpenTofu

Widest provider support, biggest talent pool

Open-source licensing is non-negotiable

OpenTofu

MPL 2.0, Linux Foundation, encrypted state

Engineers own the infrastructure

Pulumi

Real languages, real tests, real abstractions

Building an internal developer platform

Pulumi, or Terraform with strict module rules

Platform work needs software tooling

Running Kubernetes at scale

IaC for clusters, GitOps for workloads

The boundary matters more than the tool

Large org that needs standards

Terraform / OpenTofu

Mature policy as code, auditing, registries

Heavy Terraform module investment, but you want a language

Pulumi

Runs Terraform modules as-is

Mostly AWS plus one or two outside providers

CDK with a thin Terraform layer

Don't force one tool into the wrong job

Still stuck between two options? Simple tiebreaker: whichever one your on-call engineer can read fastest at 3 a.m.

Common Mistakes When Choosing an IaC Tool

IaC selection mistakes infographic
  • Choosing by syntax instead of ownership. The debate looks like HCL vs. TypeScript. The real question is who maintains this code in three years.
  • Assuming you'll stay AWS-only forever. Most teams add a SaaS provider within a year, and suddenly the AWS-only tool needs a roommate.
  • Running Kubernetes workloads through the same IaC tool. Deployments belong in GitOps. Putting them in Terraform or Pulumi gives you slow plans and endless drift.
  • Optimizing for the first deployment. The fastest tool to start with is often the hardest one to operate later.
  • Building abstractions too early. Wrapping everything in custom components before the platform settles creates a layer nobody wants to touch.
  • Migrating for taste, not for a blocker. A rewrite costs months. "The other tool is nicer" doesn't pay for it.

Final Thoughts

There's no universal winner, because these tools aren't competing on quality. They're competing on assumptions about who owns infrastructure.

Terraform assumes a platform team. Pulumi assumes software engineers. CDK assumes AWS and product teams. Match that to your company and the tool feels easy. Get it wrong and you'll fight it for years.

The biggest mistake isn't picking the "wrong" tool. It's picking for the first month instead of the next three years - after the people who wrote it have left, the infrastructure has tripled, and whoever reads the plan during an incident joined last month.

The second is thinking the tool is the strategy. How you handle state, who owns the modules, how policies are enforced, where secrets live, and where IaC ends and GitOps begins will affect your uptime far more than HCL vs. TypeScript ever will.

Infrastructure outlives frameworks, org charts, and opinions. So don't pick the tool that wins the argument today - pick the one your future team will thank you for.

Dmitriy Konstantynov

Let's arrange a free consultation

Just fill the form below and we will contaсt you via email to arrange a free call to discuss your project and estimates.