Configuring Pulumi for Infrastructure as Code
Typical situation: you have a TypeScript project, DevOps asks you to learn HCL for Terraform, and you've been writing legacy for six months. We've been through this: in a startup, during a multi-region migration, the Terraform code grew to 500+ lines, while Pulumi assembled the same infrastructure in 150 lines of TypeScript — three times less code with full functionality. That case is one of 10+ projects where we implemented Pulumi. On average, teams spend 2 weeks writing Terraform modules for a typical web application; with Pulumi, it takes 5 days. Pulumi doesn't require learning HCL, lowering the barrier for developers and saving budget.
What Problems Does Pulumi Solve?
- Complex logic and dynamic configs. Terraform with HCL struggles with generating resources based on external data. For example, creating 20 S3 buckets with different policies from a CSV file. In HCL — a tedious loop with count; in Pulumi on TypeScript — a single map with forEach, reducing code by 5x.
- Code reuse. In HCL — modules; in Pulumi — npm packages. You extract common patterns (VPC, cluster, service) into a library and import it as a regular dependency. This reduces duplication and speeds up development by 30%.
- Debugging and testing. Pulumi uses the same tools as development: TypeScript compiler, linter, unit tests. Type errors are caught at compile time, not in production. This reduces debugging time by 30% and lowers maintenance costs.
Why Pulumi is Better Than Terraform?
Pulumi is 3x faster to develop thanks to familiar languages. You use the TypeScript compiler and Jest for testing, not just terraform plan. Type errors are caught at compile time, not in production. Pulumi is also cheaper to operate: no additional tools needed for state management. As stated in the Pulumi documentation: "Pulumi uses familiar programming languages to define and manage cloud resources."
How We Do It: A Real Case
Project: a web application on AWS with RDS PostgreSQL 16, ECS Fargate, and CI/CD via GitHub Actions. Previously, 4 developers maintained Terraform code; each change took 2 days. We migrated to Pulumi in a week, reducing infrastructure management costs by $15,000 per year. The stack consisted of 3 ECS services, 2 application load balancers, 4 security groups, and 2 parameter store secrets.
Stack: TypeScript, Pulumi v3, AWS provider v6, PostgreSQL 16, ECS with Fargate. We used 2 Availability Zones, 100 GB SSD gp3, 256 CPU units, 512 MB memory, 3 tasks per service.
import * as aws from "@pulumi/aws";
import * as awsx from "@pulumi/awsx";
import * as pulumi from "@pulumi/pulumi";
const config = new pulumi.Config();
const dbPassword = config.requireSecret("dbPassword");
const vpc = new awsx.ec2.Vpc("myapp-vpc", {
numberOfAvailabilityZones: 2,
enableDnsHostnames: true,
});
const cluster = new aws.ecs.Cluster("myapp-cluster", {
settings: [{ name: "containerInsights", value: "enabled" }],
});
const db = new aws.rds.Instance("myapp-db", {
engine: "postgres",
engineVersion: "16.1",
instanceClass: aws.rds.InstanceType.T3_Medium,
allocatedStorage: 100,
dbName: "myapp",
username: "myapp",
password: dbPassword,
skipFinalSnapshot: !pulumi.getStack().startsWith("prod"),
vpcSecurityGroupIds: [dbSg.id],
dbSubnetGroupName: dbSubnetGroup.name,
storageEncrypted: true,
});
const service = new awsx.ecs.FargateService("myapp-web", {
cluster: cluster.arn,
taskDefinitionArgs: {
container: {
name: "web",
image: "registry.example.com/myapp:latest",
cpu: 256,
memory: 512,
essential: true,
portMappings: [{ containerPort: 8080 }],
environment: [
{ name: "APP_ENV", value: "production" },
{ name: "DB_HOST", value: db.endpoint },
],
secrets: [
{ name: "DB_PASSWORD", valueFrom: dbPasswordSecret.arn },
],
},
},
desiredCount: 3,
loadBalancers: [{
targetGroupArn: targetGroup.arn,
containerName: "web",
containerPort: 8080,
}],
});
export const dbEndpoint = db.endpoint;
export const serviceUrl = pulumi.interpolate`https://${loadBalancer.dnsName}`;
After migration, deployment speed increased by 40%, errors halved, and a new developer got up to speed in a day.
Work Process
- Analysis — audit of current infrastructure, choosing a provider (AWS, GCP, Azure).
- Design — stack architecture (dev/staging/prod), CI/CD integration.
- Implementation — writing code in TypeScript/Python, stack configuration.
- Testing —
pulumi preview+ unit tests in TypeScript. - Deployment — connect to CI/CD (GitHub Actions, GitLab CI) and canary release.
Tip: use Pulumi Cloud for state—it provides locking and change history. This prevents conflicts during parallel deployments.
What's Included
| Component | Description |
|---|---|
| Repository | Pulumi project with code and config |
| Stacks | dev/staging/prod with separate state |
| CI/CD | GitHub Actions / GitLab CI pipeline |
| Documentation | Deployment instructions |
| Training | 1-day workshop for the team (Pulumi training) |
| Support | 30 days after release |
Timeline Estimates
- Typical stack (AWS + PostgreSQL + ECS) — 5-7 days.
- Complex multi-region architecture — up to 14 days.
- Price is calculated individually after an audit. Typical savings: $10,000–$20,000 annually in developer time. Our service costs $3,500 for a basic three-stack setup.
How to Automate Deployment with Pulumi?
We connect Pulumi to your CI/CD in 1 day. Example for GitHub Actions:
- name: Pulumi Deploy
uses: pulumi/actions@v4
with:
command: up
stack-name: production
cloud-url: https://api.pulumi.com
env:
PULUMI_ACCESS_TOKEN: ${{ secrets.PULUMI_ACCESS_TOKEN }}
AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
At the same time, we configure Pulumi Cloud for state storage and secret rotation.
Comparison: Pulumi vs Terraform
| Criteria | Pulumi | Terraform |
|---|---|---|
| Language | TypeScript, Python, Go, C# | HCL |
| Reuse | npm/pip packages | modules |
| Testing | Jest, TypeScript compiler | only terraform plan |
| Error handling | TypeScript compilation | runtime errors |
| Cost | Community free, paid for Team and Enterprise | Community free, paid for Cloud |
| Community | actively growing | huge, mature |
| Deployment frequency | up to 10x per day | 1x per day typical |
Common Mistakes When Working with Pulumi
- Lack of state lock — if two developers run
pulumi upsimultaneously, state corruption is possible. Solution: use a backend with locking (S3 + DynamoDB). - Hardcoded stack dependency — do not use absolute resource names. Always apply
pulumi.getStack()andconfig.require. - Ignoring preview —
pulumi previewsaves hours of debugging. Always check the diff before deployment.
Our engineers have over 5 years of IaC experience; we've implemented Pulumi for 10+ projects. We guarantee fault tolerance and compliance with best practices. For more details, see the official Pulumi documentation.
Get a Pulumi setup: we'll assess your project in 1 day, just write to us. Receive a consultation on Pulumi implementation. Contact us for an audit.







