Terraform vs Pulumi vs CloudFormation: IaC Comparison
Terraform, Pulumi, and CloudFormation are the leading Infrastructure as Code (IaC) tools — Terraform uses HCL a declarative DSL, Pulumi lets you write infrastructure in real programming languages, and CloudFormation provides AWS-native template-based provisioning.
At a Glance
| Feature | Terraform | Pulumi | CloudFormation |
|---|---|---|---|
| Language | HCL (domain-specific) | TypeScript, Python, Go, C#, Java, YAML | JSON, YAML templates |
| State Management | Local/remote (S3, Terraform Cloud) | Managed (Pulumi Cloud, S3, local) | AWS-native (StackSets, drift) |
| Modularity | Modules (registry, Git, local) | Packages (npm, pip, Go modules) | Nested stacks |
| Provider Ecosystem | 2000+ providers (broadest) | 1000+ providers (Terraform-compatible) | AWS-only + 200+ resource types |
| Multi-Cloud | Excellent (AWS, Azure, GCP, K8s) | Excellent (same code, different clouds) | Limited (AWS-only) |
| Drift Detection | terraform plan (manual) | pulumi preview (manual refresh) | Automatic (CloudFormation Drift Detection) |
| Testing | Terratest, OPA, Sentinel | Unit tests (native language testing) | CloudFormation Guard, task tests |
| Learning Curve | Moderate (learn HCL syntax) | Steep (learn IaC + language patterns) | Moderate (JSON/YAML + CF functions) |
Key Differences
- Language: Terraform’s HCL is declarative — you describe desired state in
resource "aws_s3_bucket" "my_bucket" { ... }. Pulumi uses TypeScript, Python, Go, C#, or Java — you write infrastructure using familiar language constructs (loops, conditionals, classes). CloudFormation uses JSON or YAML with intrinsic functions (Fn::Join,Ref,!Sub). - State Management: Terraform stores state in a backend (S3, Terraform Cloud) — state files contain resource metadata and can be locked to prevent concurrent modifications. Pulumi uses managed state via Pulumi Cloud (free for individuals) or self-managed backends. CloudFormation manages state on AWS — no manual state files, but limited to AWS.
- Testing: Pulumi’s use of real programming languages enables unit testing with your existing test framework. Terraform requires specialized tools like Terratest or OPA policies. CloudFormation Guard provides policy-as-code validation.
- Multi-Cloud: Terraform and Pulumi both support AWS, Azure, GCP, Kubernetes, and hundreds of other providers. CloudFormation only works with AWS. If you run a multi-cloud or hybrid infrastructure, Terraform or Pulumi are necessary.
When to Choose Terraform
Terraform is the industry standard for IaC — the largest provider ecosystem, the most community modules, and the widest adoption. HCL may require learning a new language, but its declarative syntax maps perfectly to infrastructure. Terraform’s plan/apply workflow gives clear visibility into changes before they’re applied. The Terraform Registry (3,000+ modules) lets you reuse battle-tested configurations for VPCs, Kubernetes clusters, and databases. Terraform works everywhere — AWS, Azure, GCP, Kubernetes, Helm, GitHub, and on-premises.
When to Choose Pulumi
Pulumi is best for teams who want to use their existing programming language expertise for infrastructure. If your team knows TypeScript, you can write infrastructure with the same IDE, linters, type checking, and testing patterns as your application code. Pulumi excels in complex scenarios — loops create multiple resources, conditionals control resource creation, and shared code (npm packages) distributes infrastructure patterns across teams. Pulumi’s pulumi up CLI provides a similar workflow to Terraform but with richer automation possibilities through native language constructs.
When to Choose CloudFormation
CloudFormation is the best choice for AWS-only workloads where you want native integration, automatic drift detection, and no state files to manage. CloudFormation StackSets let you deploy across multiple accounts and regions with built-in permission management. CloudFormation’s drift detection runs automatically and reports resource changes. For organizations that are all-in on AWS and need minimal tooling overhead, CloudFormation provides a seamless experience within the AWS console.
Architecture Comparison
flowchart TD
subgraph Terraform
T1[HCL Config] --> T2[terraform plan]
T2 --> T3[State File]
T3 --> T4[AWS/Azure/GCP]
end
subgraph Pulumi
P1[TypeScript/Python] --> P2[pulumi up]
P2 --> P3[Pulumi Cloud State]
P3 --> P4[AWS/Azure/GCP]
end
subgraph CloudFormation
C1[YAML/JSON] --> C2[AWS CloudFormation]
C2 --> C3[AWS Drift Detection]
C3 --> C4[AWS Resources]
end
Side by Side Code Example: Create an S3 Bucket
Terraform (HCL)
resource "aws_s3_bucket" "my_bucket" {
bucket = "my-app-data-2026"
tags = {
Name = "My App Bucket"
Environment = "production"
}
}
resource "aws_s3_bucket_versioning" "my_bucket" {
bucket = aws_s3_bucket.my_bucket.id
versioning_configuration {
status = "Enabled"
}
}Pulumi (TypeScript)
import * as aws from "@pulumi/aws";
const bucket = new aws.s3.Bucket("my-bucket", {
bucket: "my-app-data-2026",
tags: {
Name: "My App Bucket",
Environment: "production",
},
});
new aws.s3.BucketVersioningV2("my-bucket-versioning", {
bucket: bucket.id,
versioningConfiguration: {
status: "Enabled",
},
});
export const bucketName = bucket.id;CloudFormation (YAML)
Resources:
MyBucket:
Type: AWS::S3::Bucket
Properties:
BucketName: my-app-data-2026
Tags:
- Key: Name
Value: My App Bucket
- Key: Environment
Value: production
MyBucketVersioning:
Type: AWS::S3::BucketVersioning
Properties:
Bucket: !Ref MyBucket
VersioningConfiguration:
Status: EnabledAll three create an S3 bucket with versioning. Terraform uses HCL’s resource blocks. Pulumi uses TypeScript with new aws.s3.Bucket(). CloudFormation uses YAML with !Ref intrinsic functions. Pulumi’s code is plain TypeScript — you get IDE autocompletion, type checking, and the ability to use loops and conditionals.
FAQ
Built by the developers of DodaTech
Doda Browser, DodaZIP & Durga Antivirus Pro