Last autumn we ran an experiment we'd been putting off for years: we built one new client project entirely on Pulumi with TypeScript, while the rest of our infrastructure stayed on Terraform. Not a weekend demo — a production project with an AWS account, CI/CD and an on-call rota, for six months. We honestly expected to start migrating everything to Pulumi afterwards. We didn't. This is a note on why.
We're writing this as a company that builds and operates cloud infrastructure for clients — the same practice that produced our older piece on deliberately boring Terraform. This one follows it: back then we argued for boredom within one tool; this time boredom picked between two.
What Pulumi genuinely does better
Let's start honestly, because online comparisons tend to skip this: Pulumi has three things we genuinely miss to this day. First, a real language. A loop, a condition and a shared function in TypeScript simply beat HCL acrobatics with count, for_each and dynamic blocks — a piece of infrastructure that took eighty lines of tricks in Terraform was twenty lines of readable code in Pulumi. Second, secrets in the state file are encrypted by default, not as an act of extra discipline. Third, unit tests over infrastructure: the project had a test asserting no S3 bucket could ever be created public — it ran in CI in seconds, no cloud needed.
Where it started to hurt
The first problem, paradoxically, is that same real language. Three senior people wrote three styles of infrastructure: one used classes and factory functions, another pure functions with config objects, the third simply a long script. All legitimate TypeScript, all passed review — but after six months the infra repo read like three projects stitched together. HCL doesn't have this problem, because HCL can't express three styles. The second problem: the infra repo inherited the entire npm ecosystem — dependabot, lockfile conflicts, minor SDK versions every two weeks. Infrastructure code that wasn't changing suddenly needed maintenance just to stand still.
And the third thing you only learn in practice: a large share of Pulumi providers are bridges over Terraform providers. When we hit a bug in ALB listener behaviour, both the issue and the fix lived in the Terraform provider, and the documentation that saved us was Terraform's. We were paying an abstraction tax on a tool we already knew how to use directly.
The deciding factor: handover
None of that alone would have settled it. What settled it is what stands at the end of every project we do: handover. Sooner or later, the infrastructure we build is taken over by someone on the client's side — an internal admin, a future vendor, sometimes one part-time person. Terraform in flat HCL can be read by any of them after a single weekend. A Pulumi project in TypeScript with abstractions from three authors needs a TypeScript developer who also understands infrastructure — and that exact person is usually not sitting at our clients' companies. The limitedness of HCL we'd spent years cursing turned out, at handover time, to be its most valuable property: it's a ceiling on cleverness.
HCL's limitedness isn't a flaw. It's a ceiling on cleverness — and infrastructure is exactly the place where you want a ceiling on cleverness.
When we'd still recommend Pulumi
So this doesn't read as a verdict: we left the pilot project on Pulumi and it runs happily to this day. We'd pick Pulumi again in three situations. When the infrastructure is owned long-term by a product team that lives in TypeScript and will never hand it over. When the infrastructure is genuinely dynamic — say, provisioning an isolated environment per tenant, where HCL really does crack. And when a team wants to test infra with the same tools as the application. None of those is the typical profile of our engagements — which is why the default stays Terraform.
If you're deciding right now what to build your infrastructure on — or you have a Terraform setup that's grown over the years into something everyone is afraid to touch — get in touch. This decision is cheap at the start and expensive three years in, and we've paid both ends of that bill ourselves.