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

  1. One box, one process family. App + Postgres + Redis on the same VPS is fine until 10k users. Resist managed services.
  2. Free tiers only, but audited. Cloudflare free is genuinely free. Email free tiers (Resend 3k emails, Brevo 300/day) are real. Check limits quarterly.
  3. 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.

Related guides