IaC¶
Domain summary
Infrastructure as Code tools that declare cloud, SaaS and on-premises resources, compute a plan against recorded state, and apply it through provider plugins. The domain covers Terraform 1.16.4 (BSL 1.1, HashiCorp, an IBM company), its open-source fork OpenTofu 1.12.6 (MPL-2.0, Linux Foundation, CNCF Sandbox), and Pulumi 3.264.0 (Apache-2.0 engine, general-purpose languages plus YAML and HCL). All three can use the same Terraform-protocol providers. They differ in license and governance, in how state is protected, and in the language you write.
Topics¶
| Topic | What it is | Current version (checked 2026-09-25) | License |
|---|---|---|---|
| OpenTofu | Open-source fork of Terraform 1.5.x under the Linux Foundation (CNCF Sandbox since 2025-04-23). Same HCL, state and providers, plus client-side state and plan encryption, early variable evaluation, provider for_each and OCI distribution |
1.12.6 (2026-08-19); 1.13 in RC | MPL-2.0 |
| Pulumi | IaC in TypeScript/JavaScript, Python, Go, .NET, Java, YAML or HCL on an open-source engine; commercial Pulumi Cloud adds state, ESC secrets, Deployments, Neo AI agent and IDP | 3.264.0 (2026-09-23), roughly weekly releases | Apache-2.0 (CLI, engine, SDKs); Pulumi Cloud proprietary |
| Terraform | HashiCorp's declarative HCL tool with the largest provider and module ecosystem; HCP Terraform and Terraform Enterprise add remote runs, policy, Stacks and HYOK | 1.16.4 (2026-09-23); 1.17 in beta | BSL 1.1 since 1.6 (licensor IBM); 1.5.7 was the last MPL-2.0 release |
How the Domain Fits Together¶
The map shows the shared provider protocol at the centre: OpenTofu forked from Terraform 1.5.x, Pulumi can run any Terraform/OpenTofu provider and even .tf files, and each tool has its own managed platform and state options.
flowchart LR
TF["Terraform 1.16<br/>(BSL 1.1)"] -->|"forked at 1.5.x"| OT["OpenTofu 1.12<br/>(MPL-2.0)"]
TF -->|"tfplugin5/6 gRPC"| PROV["Terraform-protocol providers<br/>(aws, azurerm, google, kubernetes)"]
OT -->|"tfplugin5/6 gRPC"| PROV
PU["Pulumi 3.264<br/>(Apache-2.0)"] -->|"bridged packages +<br/>Any Terraform Provider"| PROV
PU -.->|"Pulumi HCL runs .tf files"| TF
TF --> HCP["HCP Terraform / TFE<br/>(Stacks, Sentinel/OPA, HYOK)"]
OT --> TACOS["Third-party TACOS<br/>(Spacelift, env0, Scalr, Harness)"]
OT --> ENC["Client-side state and<br/>plan encryption"]
PU --> PC["Pulumi Cloud<br/>(ESC, Neo, Deployments, IDP)"]
PROV --> CLOUD["Cloud and SaaS APIs"]
Comparisons¶
| Comparison | Scope |
|---|---|
| IaC Comparison: Terraform vs OpenTofu vs Pulumi | License and governance, languages, providers, state backends, locking and encryption, testing, policy, managed platforms, migration paths, and a decision flowchart |
All comparison notes are listed in the comparisons index.
When to Use Which¶
These rules match the decision flowchart in the IaC comparison.
| Need | Reach for |
|---|---|
| Real programming languages, unit tests, Automation API, self-service platforms | Pulumi |
| HCL with an OSI open-source license and neutral foundation governance | OpenTofu |
| Client-side encryption of state and plan files regardless of backend | OpenTofu |
| HCP Terraform features (Stacks, Sentinel, HYOK, no-code modules) or IBM/HashiCorp support | Terraform |
| Existing Terraform 1.5.x or earlier and a license concern | OpenTofu (drop-in migration) |
| Existing Terraform 1.6+ configurations | Stay on Terraform, or review Terraform-only features before moving to OpenTofu |
| HCL authoring but Pulumi Cloud services (ESC, Neo, Deployments) | Pulumi with Pulumi HCL (runtime: hcl) |
Landscape¶
The main tension is between a declarative DSL (HCL in Terraform and OpenTofu) and general-purpose languages (Pulumi). HCL keeps plans reviewable by people with little programming background. General-purpose languages add loops, types, abstractions and unit tests, at the cost of a steeper abstraction curve. The line is blurring: Terraform keeps adding language features (dynamic module sources in 1.15, import inside modules in 1.16), and Pulumi now runs HCL directly.
HashiCorp relicensed Terraform from MPL 2.0 to BSL 1.1 with version 1.6 (2023). The community forked 1.5.x as OpenTofu under the Linux Foundation, and OpenTofu joined the CNCF Sandbox on 2025-04-23. IBM completed its acquisition of HashiCorp on 2025-02-27 and is now the licensor named in Terraform's license. CDKTF, HashiCorp's general-purpose-language layer, was archived on 2025-12-10, which leaves Pulumi as the main general-purpose-language option among these tools.
The provider ecosystem is the strongest moat, but it is shared: Terraform, OpenTofu and Pulumi can all run the same Terraform-protocol provider binaries. The Terraform Registry lists thousands of providers: the registry home page showed 7,335 providers and 24,598 modules in a search-engine snapshot seen 2026-09-27. OpenTofu runs its own registry at registry.opentofu.org and adds OCI distribution since 1.10.
Layered IaC
A common platform pattern is layered IaC: infrastructure teams keep low-level Terraform or OpenTofu modules, and platform teams expose them through higher-level APIs such as Pulumi components, the Pulumi Automation API, or Crossplane compositions. Developers get a self-service interface without writing provider-level code.
Single-cloud tools (AWS CDK, Azure Bicep, Google Cloud Infrastructure Manager) integrate more tightly with one provider but give up multi-cloud reach. Google's older Cloud Deployment Manager reached end of support on 2026-03-31, with Infrastructure Manager as the suggested replacement. The runner layer (often called TACOS: Atlantis, Spacelift, env0, Scalr, Harness, HCP Terraform) provides plan/apply automation, policy, drift checks and state hosting.
Key Concepts¶
State Management¶
IaC tools keep a state file that maps declared resources to real objects, which enables diff-based plans. Terraform and OpenTofu store state as JSON in a backend (local, S3, GCS, AzureRM, PostgreSQL and others, or HCP Terraform). Pulumi keeps per-stack state in Pulumi Cloud or a DIY backend (S3 and S3-compatible, Azure Blob, GCS, PostgreSQL, local file).
- Locking: prevents concurrent writes. On S3, Terraform (GA in 1.11) and OpenTofu (1.10+) support a native lock file with
use_lockfile = true; Terraform deprecated the DynamoDB locking arguments. Other backends use blob leases, lock objects or PostgreSQL advisory locks. Pulumi Cloud locks service-side, and DIY backends use lock files. - Encryption: OpenTofu encrypts state and plan files client-side since 1.7 (
aes_gcmwith keys frompbkdf2,aws_kms,gcp_kms,openbao,azure_vaultor the experimentalexternalprovider). Terraform relies on backend encryption at rest; HCP Terraform adds Hold Your Own Key (HYOK, GA 2025-09). Pulumi encrypts each secret value in state with the stack's secrets provider (Pulumi Cloud, passphrase, AWS KMS, Azure Key Vault, Google Cloud KMS or Vault Transit), including on DIY backends. - Keeping secrets out of state: ephemeral values and write-only attributes (Terraform 1.10/1.11, OpenTofu 1.11) never persist sensitive values.
- Splitting: smaller states reduce blast radius and plan time.
- Import:
importblocks (Terraform 1.5+, OpenTofu from its first release 1.6, withfor_eachsince 1.7) andpulumi importbring existing resources under management. Terraform 1.14 addedterraform queryto discover resources to import.
Plan/Apply Workflow¶
plan computes the diff between desired and recorded state without changing anything; apply executes it. Pulumi's equivalents are pulumi preview and pulumi up. Policy-as-code gates can reject a plan before any change:
- Sentinel and OPA: policy sets on HCP Terraform and Terraform Enterprise. Terraform Policy (
-policies) brings evaluation to the CLI and is GA in the 1.17 line, currently in beta. - OPA/Rego with Conftest: evaluates plan JSON from Terraform or OpenTofu in any CI system.
- Pulumi policy packs (formerly branded CrossGuard): policies written in general-purpose languages, enforced across the organization through Pulumi Cloud.
Drift Detection¶
Drift happens when live infrastructure changes outside IaC (console edits, other automation). Terraform and OpenTofu detect it during plan by refreshing state against provider APIs, and Pulumi with pulumi refresh or preview. None of the CLIs poll on their own, so continuous detection needs scheduled plans in CI or a managed platform (for example Pulumi Cloud drift detection on the Pro edition and above). Crossplane takes a different approach: Kubernetes controllers continuously reconcile managed resources against their spec.
Providers and Modules¶
Provider model
Providers are plugins that translate resource definitions into cloud API calls over gRPC (plugin protocol 5/6). The same provider binaries serve Terraform and OpenTofu, and Pulumi runs them through bridged packages or pulumi package add terraform-provider. Lock files (.terraform.lock.hcl) pin provider versions and checksums for reproducible runs.
Reusable modules come from the Terraform Registry, the OpenTofu Registry (and OCI registries since OpenTofu 1.10), private registries, or Git. Pulumi components are shipped through language package managers (npm, PyPI, NuGet, Maven, Go modules) and Pulumi's private registry, which adds type checking and richer dependency resolution.
Related Domains¶
- CI/CD: Argo CD and Flux deploy workloads onto the clusters IaC provisions
- Multi-cloud governance: policy, Crossplane and IaC across clouds
- AWS, Google Cloud and Kubernetes: the most common targets
- HashiCorp Vault and SOPS: dynamic credentials and encrypted secrets for IaC (OpenBao is an OpenTofu key provider)
Sources¶
- Terraform documentation, CHANGELOG and LICENSE (BSL 1.1)
- OpenTofu documentation, releases and CNCF project page
- Pulumi documentation and CHANGELOG
- Terraform CDK sunset notice
- Google Cloud Deployment Manager deprecation
Open Questions¶
- As Terraform (Stacks, actions, list resources, dynamic module sources) and OpenTofu (state encryption, provider
for_each, OCI distribution, Symbol Libraries) keep diverging, will providers and modules stay portable between them? - With Pulumi running HCL and Terraform adding more programming constructs, does the DSL-versus-general-purpose-language choice still decide tool selection, or do platform services (HCP Terraform, Pulumi Cloud, TACOS) decide it instead?
- What is the best practice for "state as a liability" at scale (hundreds of states) now that ephemeral values, write-only attributes, OpenTofu encryption and HYOK each cover part of the problem?