Three tools, three mental models, real tradeoffs. I have shipped infrastructure with all three. This is the practical comparison, not the marketing comparison.
The tools
Terraform (now also OpenTofu[3]) is the incumbent. HCL as the language, remote state as the coordination mechanism, a provider ecosystem that covers virtually every cloud and SaaS platform[4]. It is ten years old and the community surface is enormous.
Pulumi[1] takes the same resource model as Terraform but replaces HCL with real programming languages: TypeScript, Python, Go, C#. If you have a TypeScript codebase, Pulumi lets you define infrastructure in the same language as your application code. State lives in Pulumi Cloud (free tier generous) or a self-hosted backend.
SST[2] (formerly Serverless Stack, now in v3) is different in kind. It is a higher-level construct framework built on top of Pulumi, specifically optimised for AWS. The constructs map to real workloads — new sst.aws.Nextjs, new sst.aws.Function, new sst.aws.Bucket. The magic is the local development experience: sst dev spins up a live development environment wired to real AWS resources, with hot-reloading.
Head-to-head
| Spec | Terraform (OpenTofu) | Pulumi | SST |
|---|---|---|---|
| Language | HCL (domain-specific) | TypeScript, Python, Go, C# | TypeScript/JS only |
| State model | Remote state file (S3, Terraform Cloud) | Pulumi Cloud or self-hosted backend | SST Cloud (free tier) or self-hosted |
| Cloud coverage | Best in class: 3000+ providers | Good: mirrors Terraform providers | AWS-first, some Cloudflare |
| Blast radius on error | Explicit plan step, hard to surprise | Plan step exists, less enforced in practice | Lower blast radius — constructs, not raw resources |
| Learning curve | Medium: HCL is learnable in a weekend | Low for TS devs, higher for others | Lowest for JS/TS devs |
| Ecosystem maturity | Mature: 10 years, 3000+ providers, huge community | Growing: strong backing, enterprise adoption rising | Newer: v3 broke from v2, community smaller |
| Local dev story | None native, terraform-local workarounds | None native | First-class: sst dev spins local env with live reloading |
| Best fit | Multi-cloud or enterprise infra teams | TS/Python teams who want type safety on infra | Solo devs or small teams on AWS + Next.js |
The cloud coverage gap is real. Terraform has 3000+ providers[4]. Pulumi mirrors Terraform providers (so coverage is nearly equivalent) plus has native providers for some platforms. SST is AWS-first and the Cloudflare support is limited. If you need to manage DNS, CDN, database, object storage, and Kubernetes across AWS and GCP, SST is not the right tool.
Blast radius
Terraform's plan step is one of its best features. You run terraform plan, read the diff, confirm it is what you intended, then apply. Most teams enforce plan in CI before apply in main. This makes large destructive changes hard to do accidentally.
Pulumi has pulumi preview, which is equivalent. In practice I have seen Pulumi users skip the preview more often than Terraform users skip the plan, partly because Pulumi is more often used in scripts and automation where the preview step is optional.
SST's construct model naturally reduces blast radius because you are not describing raw resources — you are composing higher-level constructs. Deleting an sst.aws.Nextjs construct removes the construct, but SST defaults to retaining data resources (S3 buckets, RDS clusters) unless you explicitly set removal: "remove". Sensible default.
Local development: where SST wins
The local dev story is Terraform and Pulumi's biggest weakness. Neither has a first-class answer to "I want to develop my application against real cloud resources without a full deploy cycle."
SST's sst dev command is genuinely good. It runs a local proxy that routes Lambda invocations to your local machine. Your function code runs locally, gets full hot-reload, and can use console.log like a normal Node process. The resources (S3, DynamoDB, RDS) are still real AWS resources, but the compute is local. For a Next.js developer, this is close to the standard next dev experience, with the cloud wired in.
If your team's biggest pain is "the dev loop for serverless is slow," SST addresses this in a way Terraform and Pulumi do not.
Where Terraform stays the right call
I maintain my own terraform-stack[5] which covers Vercel, Supabase, Cloudflare, and DigitalOcean in one repo. There is no SST story for Vercel or Supabase. There is a Pulumi story, but the providers are less mature. For multi-cloud, Terraform is the pragmatic choice.
Enterprise compliance is another dimension. Terraform has Sentinel (policy as code), Terraform Cloud with SSO, audit logging, fine-grained permissions. These exist in Pulumi's enterprise tier but are not in SST's model at all. If your infra team needs change approval workflows and RBAC on state, Terraform is still the answer.
Pulumi's real pitch
Pulumi's pitch is not "better Terraform." It is "infra and application in the same language, same repo, same types." A TypeScript developer can write:
``` const bucket = new aws.s3.Bucket('data') const bucketName = bucket.id // this is a pulumi.Output
```
And pass bucketName directly into an application config object that is also TypeScript. The type system prevents you from using the bucket name before it is resolved. This is a genuine ergonomic improvement over HCL interpolations.
The catch: the Pulumi Output type infects your application code. You end up distinguishing pulumi.Output from string at the boundary. For small projects this is fine; for large codebases the boundary management is its own overhead.
Decision table
| Spec | Terraform | Pulumi | SST |
|---|---|---|---|
| Multi-cloud required | Yes | Yes | No |
| Existing HCL codebase | Yes | Migrate cost is high | Migrate cost is very high |
| Team knows TypeScript | Neutral | Strong yes | Strong yes (AWS only) |
| Solo dev, AWS, Next.js | Works | Works | Best fit |
| Enterprise compliance needs | Best fit | Good | Not designed for this |
| Serverless + edge functions | Verbose | Moderate | Best fit |
| Kubernetes workloads | Best fit | Good | Weak |
What I use and why
For the sarmalinux.com stack (Vercel + Supabase + Cloudflare + DigitalOcean), terraform-stack is the right call. The providers are mature, the team is one person, and multi-provider coverage is the specific requirement.
For a greenfield AWS-only Next.js project, I would reach for SST. The local dev experience and the construct model are worth the narrower coverage.
For a TypeScript team that wants to manage AWS at medium scale with type safety on their infra, Pulumi is the clear choice over Terraform.
The "one tool to rule them all" framing is wrong. Pick the tool whose model fits the problem.
OpenTofu note
If you are starting fresh with Terraform today, use OpenTofu[3] instead of HashiCorp Terraform. OpenTofu is the community fork, BSL-free, binary-compatible, and where community provider development is increasingly happening. There is no meaningful technical difference for the use cases in this post, but the licence situation is cleaner.
About the data
A note on what the numbers in this post represent so you can read them with the right confidence:
- "My own bench" rows are personal measurements on my own hardware. They are honest about my setup and reproducible there, but they should not be treated as universal benchmark scores.
- Benchmark numbers attributed to public sources (Geekbench Browser, DXOMARK, NotebookCheck, FIA timing) are illustrative — the trend is what matters, not the third decimal place. Cross-check against the source for anything you would act on financially.
- Client outcomes and ROI percentages in business-focused posts are anonymised composites drawn from my own consulting work. Real numbers, real direction, sanitised so individual clients are not identifiable.
- Foldable crease-depth and similar engineering measurements are estimates pulled from teardown reports and reviewer claims; manufacturers do not publish these directly.
- Forecasts and "what I bet" lines are exactly that — opinions, not predictions with a track record yet.
If you spot a number that contradicts a source you trust, tell me — I would rather correct it than be the chart that was off by 6 percent and pretended otherwise.