Infrastructure-as-code is the foundation of repeatable cloud operations. Three tools dominate in 2026: Terraform (declarative HCL + ecosystem), Pulumi (real programming languages), and CloudFormation (AWS-native). Here is a side-by-side comparison with a recommendation by team shape.
State management
- Terraform — state file (local or remote), locking via DynamoDB/Consul.
- Pulumi — same model, stored in Pulumi Cloud (or S3/Azure Blob self-hosted).
- CloudFormation — managed by AWS. No state file to manage.
Language
- Terraform — HCL (HashiCorp Configuration Language). Declarative.
- Pulumi — TypeScript, Python, Go, Java, .NET, YAML. Real languages.
- CloudFormation — YAML or JSON. Declarative.
Ecosystem
- Terraform — 3000+ providers. Largest community.
- Pulumi — supports every major cloud + Kubernetes + SaaS.
- CloudFormation — AWS only. Deep AWS service coverage.
Recommendation
- Multi-cloud — Terraform.
- AWS only, deep integration — CloudFormation or CDK.
- Software-engineering team that prefers real languages — Pulumi.
Plan / Apply lifecycle and drift detection
All three tools share a declarative model: you describe the desired end state, the tool computes the diff, and you apply the diff. The differences show up in the mechanics. Terraform and Pulumi both run `plan` then `apply`; CloudFormation runs a Change Set, then executes it. Pulumi adds a "preview" mode that runs in any of its supported languages, so you can express pre-conditions (asserts, guards) in real code.
- Drift detection — Terraform Cloud and Pulumi Cloud both run continuous reconciliation against the live state. CloudFormation has Drift Detection, but you must trigger it manually and it returns verbose JSON.
- Destroy / replace — all three support targeted destroys; Pulumi allows per-resource replacement with `--target`. Terraform uses `terraform taint` (legacy) or `-replace` (1.6+).
- Rollback — CloudFormation auto-rolls back on stack failure; Terraform leaves the partial state for you to manage; Pulumi keeps the state but flags failed resources.
Module ecosystem and reuse
Terraform's module ecosystem (3,000+ providers, the public registry) is unmatched for breadth. Pulumi publishes a similar set of providers but exposes them through typed SDKs, so a single module can be reused across TS, Python, and Go consumers. CloudFormation lacks a first-class module system — teams share stacks via templates and nested stacks, which work but feel heavier.
- Terraform Registry — community modules, versioned, semver-pinned in your code.
- Pulumi Packages — auto-generated from cloud APIs; published to npm, PyPI, NuGet, Maven.
- AWS CDK — CloudFormation's spiritual cousin: real languages that compile to CFN. Not in our headline trio but worth knowing.
Pricing and licensing
All three have an OSS layer. Terraform is open source under BUSL; some features (Sentinel policies, private module registry, continuous drift) require Terraform Cloud or Enterprise. Pulumi is OSS for individual use; team features (Pulumi Cloud, role-based access, encrypted secrets) require a paid tier. CloudFormation itself is free — you only pay for the AWS resources it manages.
- Terraform Cloud — free for up to 5 users; Standard and Plus tiers for larger teams.
- Pulumi Cloud — free for individuals and small teams; Business and Enterprise tiers.
- CloudFormation — included with AWS; StackSets are free; some cross-account features require an Org.
When NOT to migrate
- If your team already knows HCL and your stack is single-cloud — Terraform's switching cost is real and the benefits of Pulumi are marginal.
- If your team is small and AWS-only — CloudFormation or CDK is enough. Pulumi adds little.
- If your IaC codebase is small — none of the three will move the needle. Choose by team preference.
FAQ
- Can Terraform and CloudFormation coexist? Yes. Many teams use CloudFormation for legacy stacks and Terraform for new multi-cloud work. Use Terraform's `aws_cloudformation_stack` data source to read outputs.
- Is Pulumi faster than Terraform? Roughly comparable; Pulumi's typed SDKs catch errors at compile time, which usually shortens the dev loop.
- Which has the best AWS support? CloudFormation (native) > Terraform (excellent) > Pulumi (excellent, slightly behind on new services).
- Does OpenTofu change the calculus? OpenTofu is a fork of Terraform with full feature parity plus new additions (state encryption, dynamic providers). Worth piloting if you worry about BUSL licensing.
Testing and policy-as-code for IaC
Infrastructure changes need tests as much as application code does. The tooling is mature enough that not testing is a clear risk in 2026. The pattern is the same as for application code: lint on save, unit-test each module, integration-test against a sandbox cloud account, and enforce policy with a separate tool.
- Linting — `tflint` for Terraform, `cfn-lint` and `cfn-nag` for CloudFormation, `pulumi check` built into Pulumi.
- Static analysis + security — `checkov`, `tfsec`, `kics` scan for misconfigurations (open S3 buckets, unencrypted EBS, overly permissive IAM).
- Unit tests — Terraform `test` command (native, 1.6+), Pulumi `*_test.go` files using `pulumirpc` + assertions.
- Policy-as-code — Sentinel (Terraform Cloud), OPA/Rego (Pulumi + general), AWS Config rules (CloudFormation).
- Integration tests — spin up real cloud resources in a sandbox account, run assertions, tear down. Tools: `terratest`, `pytest` fixtures, or hand-rolled Terraform scripts.
Common team patterns and anti-patterns
The pattern that consistently works in 2026 is a monorepo of small modules per service, owned by the service team, with shared root modules for org-wide networking and security baselines. Anti-patterns include: one mega-stack with everything inside (impossible to test or review), modules per environment (dev/prod duplicates), and copy-pasted code from Stack Overflow examples.
- Good — one module per service, semantic versioning, automated drift detection, separate state per environment.
- Bad — single shared state file across teams, modules duplicated for each region, manual apply via console.
- Secret management — never commit secrets. Use AWS Secrets Manager, HashiCorp Vault, or Pulumi secrets; reference them via data sources, not literal values.






