// Stay in touch?
Products
Encore CloudEncore Cloud
Encore.tsEncore.ts
Encore.goEncore.go
PricingPricing
Book a DemoBook a Demo
Use Cases
AI-Powered DevelopmentAI-Powered Development
Event-Driven SystemsEvent-Driven Systems
Distributed SystemsDistributed Systems
Case StudiesCase Studies
ShowcaseShowcase
Resources
DocsDocs
InstallInstall
Example AppsExample Apps
Demo videoDemo video
ArticlesArticles
GitHub ReleasesGitHub Releases
Systems Operational
Company
About UsAbout Us
Swag ShopSwag Shop
ContactContact
JobsJobs
PressPress
SecuritySecurity
TermsTerms
Privacy PolicyPrivacy Policy
Data Processing AgreementData Processing Agreement
Enterprise SLAEnterprise SLA
Encore
© 2026 EncoreAll rights reserved
© 2026 Encore All Rights Reserved
GitHubDiscordYouTube

Terraform vs Pulumi: Which IaC Tool to Pick in 2026

HCL and a purpose-built DSL against real programming languages, and how the OpenTofu fork changes the math

07/08/26
8 Min Read
Marcus Kohlberg
07/08/26

Terraform vs Pulumi: Which IaC Tool to Pick in 2026

HCL and a purpose-built DSL against real programming languages, and how the OpenTofu fork changes the math

Marcus Kohlberg
8 Min Read

If you have decided to manage infrastructure as code and narrowed the field to Terraform and Pulumi, the real question is narrow: do you want infrastructure described in a declarative configuration language, or written in the same programming language as the rest of your stack? Almost everything else follows from that one choice.

This comparison covers how each tool models infrastructure, what the code looks like, how state and pricing work, and where the OpenTofu fork lands in 2026. It ends with guidance on when each tool is the better pick, and a short note on when neither is what you want.

The one difference that matters

Terraform uses HashiCorp Configuration Language (HCL), a declarative DSL built for describing infrastructure. Pulumi uses general-purpose languages: TypeScript, JavaScript, Python, Go, C#, Java, and YAML. You write infrastructure the same way you write application code, with loops, functions, classes, and your normal package manager.

Both are declarative in outcome. Pulumi code runs to build a resource graph, then Pulumi diffs that graph against state and applies the delta, the same reconcile model Terraform uses. The difference is the authoring experience, not the execution model.

Terraform / OpenTofuPulumi
LanguageHCL (declarative DSL)TypeScript, Python, Go, C#, Java, YAML
Provider ecosystemLargest; native registryBridges Terraform providers + native providers
State backendS3, GCS, Azure Blob, HCP Terraform, localPulumi Cloud, S3, GCS, Azure Blob, local
SecretsMarked sensitive; external KMS for encryptionBuilt-in encrypted secrets in state
Testingterraform validate, plan review, TerratestNative unit tests in your language + policy
LicenseBSL (Terraform) / MPL (OpenTofu)Apache 2.0
Hiring poolVery largeSmaller but growing
Learning curveLearn HCL + provider resourcesLearn Pulumi SDK; language already known

What the code looks like

Take the same task in both tools: an AWS S3 bucket, a DynamoDB table, and three environment-specific buckets created in a loop.

Terraform (HCL):

variable "environments" { type = list(string) default = ["dev", "staging", "prod"] } resource "aws_s3_bucket" "assets" { bucket = "myapp-assets" } resource "aws_dynamodb_table" "sessions" { name = "sessions" billing_mode = "PAY_PER_REQUEST" hash_key = "id" attribute { name = "id" type = "S" } } resource "aws_s3_bucket" "env" { for_each = toset(var.environments) bucket = "myapp-${each.value}" }

Pulumi (TypeScript):

import * as aws from "@pulumi/aws"; const environments = ["dev", "staging", "prod"]; const assets = new aws.s3.Bucket("assets", { bucket: "myapp-assets", }); const sessions = new aws.dynamodb.Table("sessions", { billingMode: "PAY_PER_REQUEST", hashKey: "id", attributes: [{ name: "id", type: "S" }], }); const envBuckets = environments.map( (env) => new aws.s3.Bucket(`env-${env}`, { bucket: `myapp-${env}` }), );

The HCL is more constrained and easier to read cold, and for_each handles the loop declaratively. The TypeScript is a plain array map, which is second nature to a JavaScript developer and composes with any function or npm package you already have. Neither is objectively cleaner. HCL keeps everyone in the same narrow language; Pulumi lets a strong programmer abstract aggressively, for better or worse.

State, drift, and the reconcile model

Both tools keep a state file that maps your declarations to real cloud resources, and both reconcile against it on every apply. That means both share the same failure modes: drift when someone edits a resource by hand, lock contention when two applies run at once, and the need to store state somewhere durable and shared.

Terraform and OpenTofu store state in a backend you configure: S3 with DynamoDB locking, GCS, Azure Blob, or HCP Terraform. OpenTofu added native state encryption at the file level, which Terraform still leaves to the backend (for example S3 server-side encryption).

Pulumi stores state in Pulumi Cloud by default, and encrypts secrets inside that state out of the box. You are not locked into the hosted service: pulumi login s3://my-bucket (or gs://, azblob://, or a local path) moves state to a backend you own, at no cost.

The practical upshot: secrets handling is nicer in Pulumi by default, and self-managed state is a one-line change in both. Neither tool escapes the fundamentals of stateful reconciliation.

Pricing

Terraform the CLI is free (BSL-licensed). OpenTofu the CLI is free (MPL-licensed). The paid product is HCP Terraform (formerly Terraform Cloud), which bills for managed runs, state, and policy, with a free tier for small teams.

Pulumi the CLI and SDKs are free (Apache 2.0). Pulumi Cloud is the paid product, free for individuals and billed per resource under management above the free tier. As with Terraform, you can avoid the paid tier entirely by self-managing state.

For a team that self-manages state and runs applies in its own CI, both tools cost nothing in licensing. The bill only appears if you adopt the vendor's managed control plane.

The OpenTofu factor

In August 2023, HashiCorp relicensed Terraform from MPL to the Business Source License. A coalition forked the last MPL release into OpenTofu, now under the Linux Foundation, and in 2025 IBM acquired HashiCorp. For most end users running terraform apply against their own infrastructure, the BSL changes nothing. For vendors building products on top of Terraform, and for teams with a policy preference for OSI-approved licenses, it changed a lot.

This matters to the Pulumi comparison because "we do not want to be on HashiCorp's license terms" used to be a reason teams evaluated Pulumi. In 2026 that reason mostly points at OpenTofu instead, since OpenTofu keeps HCL, the state format, and the provider ecosystem while being permissively licensed. If your objection to Terraform was legal rather than ergonomic, you probably want OpenTofu, not Pulumi. If your objection was HCL itself, Pulumi is still the answer.

When to choose Terraform (or OpenTofu)

  • You want the largest provider ecosystem and the biggest hiring pool. HCL skills are common and portable across teams.
  • You value the constraint of a declarative DSL. HCL is hard to over-engineer, which keeps infrastructure config legible for people who are not full-time programmers.
  • Your platform team already runs Terraform, and modules, runbooks, and CI are built around it.
  • You want a license and governance posture you control: pick OpenTofu (MPL, Linux Foundation) if the BSL is a problem, Terraform if it is not.

When to choose Pulumi

  • Your team lives in TypeScript, Go, Python, or C# and wants infrastructure in the same language, tested with the same tools.
  • You need real abstraction: dynamic resource generation, shared logic across stacks, or config that would be awkward in HCL.
  • You want encrypted secrets in state without wiring up an external KMS workflow.
  • You are converting existing HCL (pulumi convert) or want to reuse Terraform providers from a programming language.

A caveat on Pulumi: general-purpose languages let you build clever abstractions that are hard for the next engineer to follow. HCL's rigidity is a feature when the goal is config that anyone on the team can read a year later. Choose Pulumi for the power, and set conventions so you do not pay for it in review.

When neither is the right layer

Both tools assume infrastructure lives in a separate codebase, a separate language, and a separate state file, with the application code unaware of any of it. That split fits VMs, networking, and IAM managed by a platform team. It fits less well when the "infrastructure" is application-level: a Postgres database, a Pub/Sub topic, a cron job, an object storage bucket that one service reads and writes.

For that case, infrastructure-from-code frameworks declare those resources in the application code itself. Encore is the open-source example for TypeScript and Go, with over 12,000 GitHub stars and production users including Groupon:

import { SQLDatabase } from "encore.dev/storage/sqldb"; import { Topic } from "encore.dev/pubsub"; // Provisions managed Postgres (RDS on AWS, Cloud SQL on GCP, Docker locally). const db = new SQLDatabase("orders", { migrations: "./migrations" }); // Provisions Pub/Sub (SNS+SQS on AWS, Pub/Sub on GCP, NSQ locally). export const orderPlaced = new Topic<{ orderID: string }>("order-placed", { deliveryGuarantee: "at-least-once", });

Encore Cloud provisions the real AWS or GCP services in your own cloud account, with no separate Terraform or Pulumi module and no separate state file to reconcile. This does not replace Terraform or Pulumi for large VM fleets or regulated networking; it removes the config sprawl that grows around an application backend. For a new backend where the choice is not constrained by an existing IaC investment, it is worth a look before you commit to either tool.

Summary

Terraform and Pulumi are both solid in 2026, and the choice is not about quality. Pick Terraform or OpenTofu for the widest ecosystem, the largest talent pool, and a declarative DSL that resists over-engineering, with OpenTofu answering the license concern. Pick Pulumi if you want infrastructure in your team's own programming language with real abstraction and built-in secret encryption. And if you are standing up a new backend whose infrastructure is mostly application-level, check whether an infrastructure-from-code approach lets you skip the separate IaC layer entirely.

Deploy with Encore

Skip the separate IaC layer. Deploy a TypeScript backend with Postgres and Pub/Sub to your own AWS or GCP account in minutes.

Deploy

Related resources

  • Pulumi vs OpenTofu
  • OpenTofu vs Terraform in 2026
  • Terraform alternatives
  • Pulumi alternatives

Frequently asked questions

Is Terraform or Pulumi better in 2026?

Neither is strictly better. Terraform (and its OpenTofu fork) has the larger provider ecosystem and the bigger hiring pool, and it stays declarative in HCL. Pulumi lets you define infrastructure in TypeScript, Go, Python, or C#, which suits teams that want loops, functions, and their existing test tooling. Pick Terraform for breadth and portability, Pulumi for programming-language ergonomics.

Does Pulumi require a paid backend like Terraform Cloud?

No. Pulumi defaults to the managed Pulumi Cloud for state, but you can point it at S3, GCS, Azure Blob, or a local file with `pulumi login`. The self-managed backends are free. Pulumi Cloud has a free tier for individuals and charges per resource above it.

How does OpenTofu affect the Terraform vs Pulumi decision?

OpenTofu is the MPL-licensed, Linux Foundation fork of Terraform created after HashiCorp moved Terraform to the BSL license. It is a drop-in replacement for most Terraform workflows and shares HCL and the state format. If your objection to Terraform was the BSL license, OpenTofu removes it, which weakens one of the historical reasons teams looked at Pulumi.

Can Pulumi use Terraform providers?

Yes. Pulumi bridges the Terraform provider ecosystem, so most Terraform providers are available in Pulumi, and Pulumi also converts existing HCL with `pulumi convert`. Provider coverage is rarely the deciding factor between the two.

Do Terraform and Pulumi both use a state file?

Yes. Both track provisioned resources in state and reconcile against it on every apply. Terraform and OpenTofu store state in a backend such as S3 or HCP Terraform. Pulumi stores state in Pulumi Cloud or a self-managed backend. The concept, and its failure modes like drift and lock contention, is the same in both.

Should I use Terraform or Pulumi for a new backend?

For a brand-new backend where the infrastructure is mostly application-level (a database, a queue, cron, object storage), it is worth asking whether you need either tool. Infrastructure-from-code frameworks like Encore let you declare those resources in your application code and provision them without a separate IaC repository. For large VM fleets, networking, and IAM at scale, Terraform or Pulumi is still the right layer.

Contents
The one difference that matters
What the code looks like
State, drift, and the reconcile model
Pricing
The OpenTofu factor
When to choose Terraform (or OpenTofu)
When to choose Pulumi
When neither is the right layer
Summary
Related resources
Encore

The backend platform for humans and agents

Build backends in Go or TypeScript and run them on your own AWS or GCP, with the guardrails your team and AI agents need to ship safely.

Get started

Ready to build your next backend?

Encore is the Open Source framework for building robust type-safe distributed systems with declarative infrastructure.