How to Run a SaaS for Less Than $20/Month
Run a real SaaS for under $20/month in 2026: exact stack, architecture, services and the tradeoffs that keep a solo project profitable.
A complete, working architecture for a SaaS on less than $20/month: the exact services, the keys to keeping it profitable, and what you’re giving up.
The budget math
The target is total monthly cost < $20 including domain, DB, email and monitoring. That’s not a toy — it’s a real monolith on a small VPS with free tiers for the rest.
The architecture
flowchart LR
Users --> CF[Cloudflare Free]
CF --> Caddy[Caddy on VPS]
Caddy --> App[App + API]
App --> PG[(PostgreSQL)]
App --> Redis[(Redis)]
Everything on one Hetzner CX22 (2 vCPU / 4 GB / 40 GB NVMe).
Exact stack and costs
| Service | What for | Cost |
|---|---|---|
| Hetzner CX22 VPS | App + Postgres + Redis + Caddy | $4.49 |
| IPv4 | Public IP | $0.48 |
| Domain (.dev / .com) | Brand | $0.08–2 |
| Cloudflare Free | CDN, TLS, WAF, cache | $0 |
| PostgreSQL (on VPS) | Data | $0 |
| Redis (on VPS) | Cache, queues, sessions | $0 |
| Email (Resend Free / SMTP) | Transactional | $0 |
| Backups (borg + Backblaze B2) | Snapshots | $0.006/GB |
| Monitoring (Uptime Kuma self-hosted) | Alerts | $0 |
| Total | ≈ $5–7/month |
Realistic total: $6/month, with a $14/month buffer for surprises (DOMAIN renewal, traffic spikes, an extra snapshot).
The three rules that make it work
- One box, one process family. App + Postgres + Redis on the same VPS is fine until 10k users. Resist managed services.
- Free tiers only, but audited. Cloudflare free is genuinely free. Email free tiers (Resend 3k emails, Brevo 300/day) are real. Check limits quarterly.
- No AI on the hot path. LLM calls are the biggest hidden cost; either price them in per-call or gate them behind the paid plan.
Deployment on the cheap
# docker-compose.yml on the VPS
services:
app:
image: ghcr.io/you/saas:latest
restart: unless-stopped
environment:
DATABASE_URL: postgres://saas:${DB_PASS}@db:5432/saas
REDIS_URL: redis://redis:6379
db:
image: postgres:17
restart: unless-stopped
volumes: ["pgdata:/var/lib/postgresql/data"]
redis:
image: redis:7
restart: unless-stopped
One file, docker compose up -d, Caddy in front issuing TLS. Deploy cost: $0 extra and 5 minutes.
What you’re giving up
- No managed high availability: one machine = risk of downtime during upgrades or if the host fails. Acceptable for an MVP; mitigate with daily offsite backups and documented restore.
- No auto-scaling: traffic spikes are handled by queues and caching, or by paying for a bigger box when they become permanent.
- No multi-region: fine for a niche/indie SaaS; Cloudflare edge cache covers static and API GETs.
When to upgrade to the $30–40 plan
-
2,000 DAU or sustained 30% CPU
- DB disk >80% on a weekly basis
- You need a second environment for staging
- Revenue consistently covers the upgrade
Upgrade path: same Compose file, larger VPS (CX32/$8.49) or split DB to its own box. No re-architecture needed.
Production checklist
- Daily offsite borg backup with monthly restore test
- Uptime Kuma alerting to Telegram
- Cloudflare caching + HTTPS forced
- Budget cap alert on every paid service
- Staging = one extra docker compose project
Common problems
- The $20 plan creeps to $60: the culprit is almost always email/LLM/managed services. Audit monthly.
- Backups on the same disk: they cost nothing but protect against nothing. Offsite or it didn’t happen.
- IPv6-only temptation: Hetzner can do it, but the $0.48/mo IPv4 avoids a world of email/API pain.
Conclusion
A real SaaS — auth, DB, background jobs, TLS, backups, monitoring — runs well under $20/month on a single Hetzner VPS with free-tier satellites. The discipline is choosing one box and auditing free tiers, not adding services.