AWS hosting made easy
I host my hobby projects on PaaS platforms like Heroku and Render because I want:
- Scalability without days of infrastructure yak shaving
- A containerised local dev environment that runs near-identical to production
But these platforms get expensive. Add a backend server, a background worker, Postgres, a Redis queue, and you’re looking at $20+ per project per month. Multiply by a few projects and it adds up fast.
I’ve avoided AWS despite its near-free pay-per-use pricing because of the infrastructure yak shaving. My platform teams take sprints to wire up AWS in complex environments. And you can’t replicate Lambda, DynamoDB, and EventBridge locally for reliable test-driven development.
Maybe things have changed.
Claude Code with Opus 4.6 writes Pulumi infrastructure. LocalStack replicates AWS services locally. The Three Musketeers pattern (Make + Docker + Docker Compose) means every command runs in a container, local and CI alike. No “works on my machine.”
To test this theory I built myself an AI-powered blog curator at https://github.com/lukerohde/reeds.
What it does
It crawls 10 tech blogs I follow (Simon Willison, Karpathy, Martin Fowler, Charity Majors, and others). Each morning it pulls new articles, uses Claude Haiku to filter out noise, Sonnet to summarise in the author’s own words, then Sonnet again to pick the 10 most interesting. Renders a clean HTML digest page.
The AWS stack
EventBridge cron (5am AEST daily)
│
├─→ Lambda: crawler
│ RSS feeds → article content → DynamoDB
│
└─→ Lambda: digest (10 min later)
DynamoDB → relevance filter (Haiku)
→ summarise (Sonnet)
→ curate top 10 (Sonnet)
→ render HTML → S3
│
CloudFront CDN
│
ACM certificate
│
Route53 DNS
140 lines of Pulumi Python. That’s the entire infrastructure definition.
CI/CD
Two GitHub Actions workflows, both triggered on push to main:
deploy-infra.yml runs on changes to infra/, backend/, or config/. It builds Lambda packages, previews the Pulumi diff on PRs, and applies on merge. AWS credentials come via OIDC, no static keys stored in GitHub.
deploy-site.yml runs on changes to public/. Syncs static assets to S3 and invalidates CloudFront.
Local development
Every command runs through Docker Compose. LocalStack provides DynamoDB and S3 locally. No AWS account needed for development.
make local-up # start LocalStack, create table + bucket
make local-crawl # fetch real RSS feeds into local DynamoDB
make dev # AI summarise + curate → preview HTML in browser
Only thing you need is an ANTHROPIC_API_KEY. The prompt engineering loop is tight: edit config/config.yaml, run make local-reset && make dev, see the result.
The same Docker Compose file defines containers for the crawler, digester, Pulumi, and AWS CLI. Same Python 3.12 image the Lambdas run. Same dependencies. Same code path.
Testing with AI
The test suite is a Claude Code slash command (/test-all) that runs five layers: unit tests, Lambda package verification, integration tests against LocalStack, deployed infrastructure health checks (EventBridge rules, Lambda status, resource policies, live invocations), and manual spot checks. It produces a single pass/fail report.
That’s a subject for another post.
Hosting cost
| Resource | Monthly cost |
|---|---|
| Lambda (2 functions, ~60 invocations/month) | Free tier |
| DynamoDB (PAY_PER_REQUEST) | Free tier |
| EventBridge (2 schedules) | Free |
| S3 (~10KB HTML/day) | ~$0.001 |
| CloudFront | Free tier |
| ACM certificate | Free |
| Route53 hosted zone | ~$0.50 |
| Total | < $1/month |
One evening
This was built in one evening. Claude Code wrote the Pulumi infrastructure, the LocalStack setup, the Docker Compose services, the Makefile, and the GitHub Actions pipelines. I steered.
The combination of AI-assisted infrastructure-as-code, LocalStack, and the Three Musketeers pattern gives you what PaaS promises (fast setup, local dev parity, simple deploys) at AWS prices (nearly free). It also starts to solve the hard problem of infrastructure testing, because if you can run the full stack locally, you can test it before it ships.