Terraform uses HCL. Pulumi uses TypeScript, Python, Go, or C#. Loops, conditionals, functions — real programming for real infrastructure.
What is Pulumi?
Pulumi is an infrastructure-as-code platform that lets you define cloud resources using general-purpose programming languages. No YAML, no HCL — just code you already know.
Why Pulumi
1. Real Programming Languages
import * as pulumi from "@pulumi/pulumi";
import * as aws from "@pulumi/aws";
// Create a VPC
const vpc = new aws.ec2.Vpc("main", { cidrBlock: "10.0.0.0/16" });
// Create subnets with a loop
const subnets = ["a", "b", "c"].map((az, i) =>
new aws.ec2.Subnet(`subnet-${az}`, {
vpcId: vpc.id,
cidrBlock: `10.0.${i}.0/24`,
availabilityZone: `us-east-1${az}`,
})
);
// Conditionally create resources
if (pulumi.getStack() === "production") {
new aws.rds.Instance("db", {
engine: "postgres",
instanceClass: "db.r5.large",
allocatedStorage: 100,
vpcSecurityGroupIds: [dbSg.id],
});
}
2. Multi-Cloud Support
// AWS
const bucket = new aws.s3.Bucket("data");
// Google Cloud
const gcsBucket = new gcp.storage.Bucket("data");
// Azure
const container = new azure.storage.BlobContainer("data");
// Cloudflare
const worker = new cloudflare.WorkerScript("api", { content: script });
// Kubernetes
const deployment = new k8s.apps.v1.Deployment("app", { /* ... */ });
3. Reusable Components
// Create reusable infrastructure components
class WebService extends pulumi.ComponentResource {
public readonly url: pulumi.Output<string>;
constructor(name: string, args: { port: number; image: string }) {
super("custom:WebService", name);
const lb = new aws.lb.LoadBalancer(`${name}-lb`, { /* ... */ });
const service = new aws.ecs.Service(`${name}-svc`, {
taskDefinition: createTask(args.image, args.port),
loadBalancers: [{ targetGroupArn: tg.arn, containerPort: args.port }],
});
this.url = lb.dnsName;
}
}
// Use it
const api = new WebService("api", { port: 3000, image: "myapi:latest" });
const web = new WebService("web", { port: 80, image: "myweb:latest" });
4. Testing Infrastructure
import * as pulumi from "@pulumi/pulumi";
import { describe, it, expect } from "vitest";
describe("infrastructure", () => {
it("should create bucket with tags", async () => {
const bucket = new aws.s3.Bucket("test", {
tags: { Environment: "test" },
});
const tags = await pulumi.output(bucket.tags).apply(t => t);
expect(tags?.Environment).toBe("test");
});
it("should not expose ports publicly", async () => {
const sg = new aws.ec2.SecurityGroup("test", { /* ... */ });
// Verify no 0.0.0.0/0 ingress rules
});
});
5. State Management
# Pulumi Cloud (free for individuals)
pulumi login
# Self-managed (S3, Azure Blob, GCS, local)
pulumi login s3://my-state-bucket
pulumi login file://~/.pulumi
Pulumi vs Terraform vs CDK
| Pulumi | Terraform | AWS CDK | |
|---|---|---|---|
| Language | TS, Python, Go, C# | HCL | TS, Python, Java |
| Cloud support | 100+ providers | 3000+ providers | AWS only |
| Loops/conditions | Native | Limited | Native |
| Testing | Standard test frameworks | terratest | CDK assertions |
| State | Cloud or self-managed | Cloud or self-managed | CloudFormation |
| License | Apache 2.0 | BSL | Apache 2.0 |
Free Tier
| Feature | Free (Individual) |
|---|---|
| Projects | Unlimited |
| Resources | Unlimited |
| State management | Included |
| Deployments | Unlimited |
| Team members | 1 |
Getting Started
# Install
curl -fsSL https://get.pulumi.com | sh
# Create project
pulumi new typescript
# Deploy
pulumi up
# Destroy
pulumi destroy
The Bottom Line
Pulumi lets you use real programming languages for infrastructure. If you've ever wished Terraform had proper loops and functions, Pulumi is the answer.
Need data tools? I build scraping solutions. Check my Apify actors or email spinov001@gmail.com.
Top comments (0)