Pulumi vs Terraform: Which to Use? (2026)
Pulumi vs Terraform compared — real programming languages vs HCL for infrastructure as code, and whether a bootstrapped founder needs either.
Table of contents8 sections
The Night HCL Made Me Want to Quit
Late 2024. Same wreckage I keep confessing to on this site — the URL shortener with zero users that I’d bloated into a pile of hand-clicked cloud resources, then tried to rescue with Terraform. I’d already made peace with the state file and the import dance (that whole saga is here). Now I was just… writing HCL. Block after block after block.
And I needed three near-identical storage buckets, so I copy-pasted the same block three times, changing one character each. Then I needed five subnets, went looking for Terraform’s for_each, got the syntax wrong, stared at a count example, got that wrong too, and sat there at 1 AM thinking one thought with total clarity:
I am a programmer. Why can’t I just write a for loop?
That’s the itch Pulumi scratches. Same category of tool as Terraform — infrastructure as code, provisions your cloud, keeps state — but instead of inventing its own configuration language, it lets you describe infrastructure in a real one: TypeScript, Python, Go, C#, Java. A for loop is a for loop. That night, it sounded like heaven. Let me tell you where it actually is heaven, where it quietly isn’t, and — because this is the Broken Engineer Guide — why you probably need neither yet.
The One Real Difference: HCL vs a Real Language
Strip away the noise and there’s a single decision underneath “Pulumi vs Terraform”: what do you write your infrastructure in?
Terraform, from HashiCorp, uses HCL — HashiCorp Configuration Language. It’s a domain-specific language, purpose-built for describing infrastructure and nothing else. You write blocks that declare “I want a bucket, a VPC, a database,” and Terraform makes the cloud match. HCL isn’t a programming language; it’s a config format with just enough logic (variables, count, for_each, conditionals) bolted on to keep you from repeating yourself too badly.
Pulumi throws that idea out. There’s no Pulumi language. You write your infrastructure in a language you already know — a .ts or .py file — importing Pulumi as a library, calling new aws.s3.Bucket(...) like any constructor. Under the hood it does what Terraform does: builds a graph of resources, diffs against state, talks to the cloud API. But your source of truth is a real program, not a config file.
Everything else people argue about is downstream of this one fork in the road. Loops, testing, abstraction, who can read your code, how big the ecosystem is — it all traces back to HCL, or a language with a compiler and a package manager?
What a Real Language Actually Buys You
The upside is real, and to a strong developer it’s seductive.
Control flow that just works. Need ten subnets? It’s a for loop, not count and index math. A resource only in production? A plain if. HCL can do versions of all this, but it fights you — for_each over maps, dynamic blocks, ternaries crammed into one line. In Pulumi you write the code the way you’d write any code.
Real abstractions. You can wrap a chunk of infrastructure in a class or function and reuse it with type-checked inputs. “A standard service” — its bucket, database, DNS record — becomes a component you instantiate, your IDE autocompleting the arguments and yelling when you pass a string where it wants a number.
Actual tests. This is the one that made me sit up. Because a Pulumi program is just a program, you test it with the tools you already use — TypeScript with Jest, Python with pytest, Go with its testing package. A real unit test — “does my code refuse to create a public bucket?” — runs in milliseconds, no cloud call.
Here’s the honest catch: a real language also gives you real ways to make a mess. Clever inheritance, a helper abstracted three layers too deep, a loop nobody can trace six months later. HCL’s dumbness is partly a feature — it’s hard to write cursed HCL. Hand an engineer a full programming language to define infrastructure and, well, you’ve met engineers. I over-engineer for sport; giving me classes to model my cloud is how a weekend disappears.
Where HCL Actually Wins
I came in ready to crown Pulumi. Then I thought about it like a business, not a programmer having fun.
Everyone can read HCL. It’s declarative and boring on purpose. A block that says resource "aws_s3_bucket" "uploads" means exactly one thing — a junior, a DevOps hire, or future-you at 3 AM all read it the same way. A Pulumi program written by a clever TypeScript dev can be genuinely hard for the next person to follow; you have to understand their code, not just their infrastructure.
The ecosystem is not close. This is the big one. Terraform has been the default for years, so the tutorials, the StackOverflow answers, the pre-built modules, the “how do I do X on AWS” posts are overwhelmingly HCL — its registry alone has roughly 4,000 providers. Hit a weird edge case at midnight and the odds someone already solved it in HCL are just higher. Pulumi can bridge Terraform’s providers, so it reaches most of the same clouds — but bridged docs aren’t native docs, and the crowd is still mostly on the Terraform side.
Constraint is underrated. A full programming language is also a temptation to turn infrastructure into a software project — the exact trap I fall into. Sometimes the tool that won’t let you be clever is the tool that ships.
State: Same Idea, Different Home
Both tools keep state — a ledger mapping “the bucket I called uploads in my code” to “the actual bucket in the cloud.” It’s how either one knows what already exists so a second run is a safe no-op instead of a duplicate disaster. (I went deep on why that file becomes the most dangerous object you own in the Terraform import guide; it applies just as much here.)
The difference is where the state lives by default. Terraform hands you a terraform.tfstate file and it’s on you to put it somewhere safe with locking before two people run apply at once and orphan live resources.
Pulumi nudges you toward Pulumi Cloud, a managed backend that stores state, handles locking, and shows deploy history in a web UI. The part that matters for a bootstrapper: the Individual tier is free forever — one user, unlimited projects and stacks, state included — and Team plans start at $40/month for up to ten. But you’re not forced into it. The CLI and SDKs are open source (Apache 2.0), and you can self-manage state in an S3 bucket, Azure Blob, Google Cloud Storage, or a local file — exactly like Terraform. So state isn’t really a reason to pick one over the other. Both solve it; Pulumi just hands you a comfortable default for free.
The OpenTofu Factor
You can’t compare these two in 2026 without the license mess — it’s half the reason people are shopping around at all.
August 2023: HashiCorp relicensed Terraform from the open-source MPL to the Business Source License — source-available, restricted, not OSI-approved open source. The community revolted. A fork called OpenTofu spun up almost overnight, kept the MPL, and became a CNCF project in April 2025. It’s a near drop-in — you type tofu instead of terraform — and it’s matured fast; OpenTofu 1.12 landed in May 2026 with features Terraform hadn’t shipped. Then the twist: IBM closed its $6.4 billion acquisition of HashiCorp in February 2025, so Terraform is now an IBM product. (Full fork history in the Terraform Registry post.)
Where does Pulumi sit in all this? Outside the drama. Its core has been plain Apache 2.0 the whole time — no relicense, no fork, no BSL asterisks. For a founder spooked by the HashiCorp episode, that clean license story is a genuine point in Pulumi’s favor; it never gave anyone a reason to fork it.
So the honest 2026 lineup is three tools, not two: Terraform (biggest ecosystem, now IBM, BSL), OpenTofu (the open fork, MPL, growing), and Pulumi (real languages, Apache 2.0). The trade, in one line: Pulumi gives you a better authoring experience; Terraform and OpenTofu give you a bigger safety net. Which matters more depends on who you are — and on whether you should be down here at all.
The Broken Engineer Verdict: You Probably Need Neither
Here’s the part the tutorials and vendor blogs never lead with, because Pulumi wants you writing TypeScript and IBM wants you writing HCL.
If you’re a solo founder in 2026, you almost certainly need neither Pulumi nor Terraform. Not yet.
Ask the honest question before “which one”: how much cloud infrastructure do I actually run? If your stack is Vercel for the frontend, Railway or Fly.io for the backend, and Neon for Postgres — the answer is basically zero. No VPC to stand up, no fleet of instances, no tangle of IAM policies to describe in any language. Those platforms are your infrastructure layer, hidden behind a git push. Choosing between HCL and TypeScript to provision infrastructure you don’t have is arguing about paint for a house you haven’t bought.
Both tools earn their keep at the same moment: when you have sprawl — dozens of resources on AWS or Google Cloud, multiple environments that must stay identical, a team reviewing infra changes in pull requests, and often a separate tool like Ansible configuring the servers you just provisioned (Terraform vs Ansible is a different fight entirely). That’s a good problem; it usually means real revenue. It is not a $0 MRR problem. (It’s the same layer where I convinced myself I needed a Kubernetes cluster for a redirect service — that confession is here.)
And if you’re genuinely there — real infra, and you’re a strong TypeScript or Python dev who’d rather write code than learn a DSL — Pulumi is legitimately appealing; the testing story alone can justify it. But if you want the biggest ecosystem and the most people who’ve hit your exact problem, Terraform or OpenTofu is the safer default. Both are fine. The choice is real — but it’s a rich person’s choice.
I reached for Terraform in that 2024 cleanup, and window-shopped Pulumi the same night, for the broken reason I reach for everything: I’d manufactured an enterprise problem so I could go learn the enterprise tool. If I’d just shipped that thing to Railway like a sane person, there’d have been nothing to provision in either language.
The Bottom Line
Pulumi and Terraform do the same job — provision cloud infrastructure as code — and the whole “vs” is one choice: a real programming language (Pulumi’s loops, abstractions, unit tests) or a purpose-built DSL (Terraform’s HCL, dumber on purpose but backed by the biggest ecosystem around). Pulumi stayed clean Apache 2.0 while Terraform went BSL and spawned OpenTofu — a three-horse race, really.
But the deepest lesson isn’t the comparison — it’s the altitude. Both tools live below your product, on infrastructure you own and operate. Managed platforms exist so you don’t have to live down there until you’ve earned the right to. The best infrastructure code is the code Vercel already ran for you.
Pick your language the day you’re drowning in cloud consoles and codifying real infra — Pulumi if you’re a developer at heart, Terraform or OpenTofu if you want the herd’s ecosystem behind you. Not before, to feel like a real engineer. I did it to feel like a real engineer, for a product with no users. Don’t be like me. (Still assembling the cheap stack that makes all of this unnecessary? Start with the broke solopreneur’s survival guide and where I actually deploy.)
This is the Broken Engineer Guide. I over-engineer everything, fail at business, and share the scars so you can skip a few. Go build something that doesn’t need a state file — in any language — yet.
