Terraform uses HCL — a domain-specific language that can't do loops properly, has no real functions, and forces you to learn a new syntax. Pulumi lets you define infrastructure in TypeScript, Python, Go, or C#. Real languages. Real IDEs. Real testing.
What Pulumi Gives You for Free
- Infrastructure as real code — TypeScript, Python, Go, C#, Java, YAML
- 100+ cloud providers — AWS, Azure, GCP, Kubernetes, Cloudflare, and more
- Pulumi Cloud — state management, secrets, CI/CD (free tier available)
- Testing — unit test your infrastructure with standard testing frameworks
- Automation API — embed Pulumi in your own tools
- AI Assist — natural language to infrastructure code
Quick Start
curl -fsSL https://get.pulumi.com | sh
pulumi new aws-typescript
Real Code vs HCL
Terraform (HCL):
resource "aws_s3_bucket" "site" {
count = length(var.environments)
bucket = "myapp-${var.environments[count.index]}"
}
# Need a loop? Use count or for_each (limited)
# Need a function? Write a module (complex)
# Need a conditional? Use ternary (ugly)
Pulumi (TypeScript):
const environments = ['dev', 'staging', 'prod'];
const buckets = environments.map(env =>
new aws.s3.Bucket(`site-${env}`, {
bucket: `myapp-${env}`,
tags: { Environment: env }
})
);
// Real functions, real loops, real conditionals
if (stack === 'prod') {
new aws.cloudfront.Distribution('cdn', {
origins: [{ domainName: buckets[2].bucketDomainName }]
});
}
Real-World Example: Full Stack on AWS
import * as pulumi from '@pulumi/pulumi';
import * as aws from '@pulumi/aws';
// VPC
const vpc = new aws.ec2.Vpc('main', {
cidrBlock: '10.0.0.0/16',
enableDnsHostnames: true,
});
// Database
const db = new aws.rds.Instance('postgres', {
engine: 'postgres',
instanceClass: 'db.t3.micro',
allocatedStorage: 20,
dbName: 'myapp',
username: 'admin',
password: dbPassword.result,
vpcSecurityGroupIds: [dbSg.id],
skipFinalSnapshot: true,
});
// Container service
const cluster = new aws.ecs.Cluster('app');
const service = new aws.ecs.FargateService('api', {
cluster: cluster.arn,
desiredCount: 2,
taskDefinition: taskDef.arn,
});
// Outputs
export const dbEndpoint = db.endpoint;
export const serviceUrl = lb.dnsName;
Testing Infrastructure (Impossible in Terraform)
import * as pulumi from '@pulumi/pulumi/automation';
import { describe, it, expect } from 'vitest';
describe('Infrastructure', () => {
it('creates S3 bucket with correct tags', async () => {
const stack = await pulumi.LocalWorkspace.createOrSelectStack({
stackName: 'test',
projectName: 'myapp',
program: async () => {
const bucket = new aws.s3.Bucket('test', {
tags: { Environment: 'test' }
});
return { bucketId: bucket.id };
}
});
const result = await stack.preview();
expect(result.changeSummary.create).toBe(1);
});
});
Pulumi vs Terraform
| Feature | Pulumi | Terraform |
|---|---|---|
| Language | TS, Python, Go, C#, Java | HCL only |
| IDE support | Full (autocomplete, types) | Limited |
| Testing | Standard test frameworks |
terraform plan only |
| Loops/conditionals | Native language features | count/for_each (limited) |
| State | Pulumi Cloud or self-managed | Terraform Cloud or S3 |
| Secrets | Built-in encryption | External (Vault, etc.) |
| Learning curve | Know a language → ready | Must learn HCL |
Who's Using Pulumi
- Snowflake, Mercedes-Benz, Lemonade in production
- Growing fast: 20K+ GitHub stars
- Import existing Terraform configs with
pulumi convert
The Verdict
If you already know TypeScript or Python, Pulumi lets you manage infrastructure without learning HCL. Real code means real IDE support, real testing, and real abstractions. The future of IaC speaks your language.
Need help building production web scrapers or data pipelines? I build custom solutions for startups and enterprises. Reach out: spinov001@gmail.com
Check out my awesome-web-scraping collection — 400+ tools for extracting web data.
Top comments (0)