Last month my hosting bill hit $47. For a side project with 200 users. That's insane.
So I spent a weekend rebuilding my entire stack on free tiers only. Three months later: $0/month, 99.98% uptime, faster page loads than before.
Here's the exact setup — and why I think paying for AWS as an indie dev in 2026 is mostly a bad habit.
The $47/month mistake
My old stack:
| Service | Cost/month | What it did |
|---|---|---|
| AWS EC2 t3.small | $15.20 | ran a 400MB Node app |
| RDS db.t3.micro | $13.50 | Postgres with 800MB of data |
| CloudFront + S3 | $9.80 | static assets |
| Route53 + misc | $8.50 | DNS, data transfer surprises |
| Total | $47.00 | for 200 users 🤡 |
The EC2 instance averaged 3.2% CPU utilization. I was paying for a server that was asleep 97% of the time.
The $0 stack that replaced it
| Layer | Service | Free tier limit | My usage |
|---|---|---|---|
| Hosting | Vercel | 100GB bandwidth, 125K serverless invocations/day | 4.1GB / ~3K invocations |
| Database | Neon | 0.5GB storage, 190 compute hours | 340MB, autosleeps |
| CDN + DNS | Cloudflare | Unlimited bandwidth, free DDoS protection | everything proxied |
| Auth | Supabase Auth | 50K MAU | 200 MAU |
| Cron jobs | Cloudflare Workers | 100K requests/day | 12 invocations/day |
| Total | $0.00 |
The actual migration code
Moving Postgres from RDS to Neon took 20 minutes:
# Dump from RDS
pg_dump -h mydb.abc123.us-east-1.rds.amazonaws.com \
-U postgres -Fc myapp > backup.dump
# Restore to Neon (connection string from dashboard)
pg_restore -h ep-cool-frog-123456.us-east-2.aws.neon.tech \
-U alex -d myapp --no-owner backup.dump
The Neon serverless driver made cold starts a non-issue:
import { neon } from '@neondatabase/serverless';
const sql = neon(process.env.DATABASE_URL!);
export async function getUsers() {
// HTTP-based, no connection pooling needed on serverless
return await sql`SELECT * FROM users LIMIT 50`;
}
Cloudflare Worker replaced my $8/month cron service:
export default {
async scheduled(event: ScheduledEvent, env: Env) {
await fetch('https://myapp.vercel.app/api/cleanup', {
headers: { Authorization: `Bearer ${env.CRON_SECRET}` },
});
},
};
# wrangler.toml — runs daily, costs $0
[triggers]
crons = ["0 3 * * *"]
The results after 90 days
- Cost: $564/year → $0/year
- p95 latency: 340ms → 180ms (Cloudflare's edge is closer to my users than us-east-1 was)
- Uptime: 99.98% (one 4-minute Vercel incident in May)
- Deploy time: 8 minutes (git push + CI) → 40 seconds
The controversial part
I'll say it: most indie devs paying for AWS/GCP are doing it out of habit, not necessity. The free tiers of Vercel + Neon + Cloudflare + Supabase comfortably handle a side project up to ~50K monthly users. By the time you outgrow them, you'll have revenue to pay for infrastructure — or you'll know exactly which bottleneck to pay for, instead of renting a sleeping EC2 instance.
Yes, vendor lock-in is real. Yes, cold starts exist (Neon wakes in ~300ms, Vercel functions in ~50ms). Neither mattered for my app. They probably don't matter for yours either.
I'm now using the money I saved on better tooling — including a free AI coding setup (details here) that replaced my paid Copilot subscription.
What's in your free-tier stack? Anyone running production traffic on $0/month — where did it break first?
Top comments (0)