Infrastructure as Code: Building the AWS Backbone
VPC, RDS, SQS, AWS Batch, three Lambda workers, CloudFront, S3 — all in Pulumi Python. And the reserved env var that costs you a failed deploy.
The pipeline needed to become a SaaS. That meant reproducible, auditable infrastructure — Pulumi Python for everything. No manual console configuration. Every resource defined in code.
What Plan 1 built
- Networking: VPC, security groups: ALB (80/443 from internet), ECS (8000 from ALB only), RDS (5432 from ECS only). Strict least-privilege at the network layer.
- RDS: Postgres 14,
db.t3.medium, private subnets only, encrypted at rest. - SQS: Three FIFO job queues with distinct priorities (Starter/Pro/Enterprise), one standard webhook queue, DLQs on all of them.
- AWS Batch: Three compute environments and queues with priority weights 10/20/30 — same job definition, different priority. The queue you're in determines how fast you get a compute instance.
- Lambda workers:
job_dispatcher(SQS FIFO → Batch submit_job),webhook_delivery(SQS → HTTP POST with exponential backoff: 30s/300s/1800s, DLQ after 3 failures),data_retention(nightly cron: deletes expired S3 objects + DB records). - CloudFront + S3: Dashboard bucket (static), distribution with two behaviors:
/api/*→ ALB (with path rewrite),*→ S3 (with SPA rewrite). - OIDC for GitHub Actions: No stored credentials. IAM role with GitHub OIDC trust policy, assumed by CI on every deploy.
The reserved env var gotcha
Lambda internally injects AWS_DEFAULT_REGION, AWS_REGION, and all credential env vars. If you set any of them explicitly in Pulumi's environment.variables, the Lambda service returns a 400 InvalidParameterValueException at deploy time.
The error message says only "reserved." It took one failed deploy to learn this permanently. The fix is removing those keys from the Pulumi config — Lambda provides them automatically.
Why Pulumi over Terraform
Python. The infrastructure uses the same language as the application code. Type checking, real loops, real conditionals, real imports — not HCL. When the infra gets complex (and it will), you want a real programming language.