I run four apps — MyOG.social, Stacknaut.com, AltCaption.com, and ToLocaltime.com — on a single ~$30/month Hetzner ARM server. TheBlue.social is older and still runs on Render. I used Heroku years ago, then Render for a couple of years. Both were fine for deployment. I switched to self-hosting for cost, control, and performance.

Cost

~$30/month for four apps with PostgreSQL, background workers, and the whole stack on one server.

The cost stays flat. More traffic doesn’t change my bill — I’m paying for the server, not per-request or per-seat. If I need more capacity, I bump to the next server tier. Still cheaper than any PaaS.

Control

On my server, I pick the OS, the Docker version, the PostgreSQL config, the backup schedule, the firewall rules. And I make those decisions once — they’re encoded in Terraform and Kamal configs. Spinning up a new project is the same setup, same commands. I’m not dependent on a platform’s roadmap or pricing decisions.

Performance

My app and database run on the same machine. Database queries are sub-millisecond — no network hop. On most PaaS setups, the database is a separate service with network overhead on every query.

The ~$30 server gives me dedicated vCPUs and RAM.

DevOps in 2026

Setting up a server in 2015 meant configuring Nginx, managing SSL certificates by hand, writing systemd service files, and hoping you didn’t miss a security update.

Now it’s Docker and Kamal. I define my app in a Dockerfile, my infrastructure in Terraform, and my deployment in a Kamal config. One command provisions the server. One command deploys the app. SSL is automatic via Let’s Encrypt through kamal-proxy.

I spend maybe 30 minutes a month on maintenance — OS updates, checking disk space, reviewing logs. My Telegram bot pings me if anything needs attention.

Scaling

A single Hetzner ARM server handles far more traffic than most indie SaaS apps will see. PostgreSQL on one server can do thousands of queries per second.

If I outgrow one server — a great problem to have — Kamal supports multi-server deployments. Move the database to its own box, add a second web server, and kamal-proxy load-balances between them.

What I Self-Host (and Don’t)

  • MyOG.social, Stacknaut.com, AltCaption.com, ToLocaltime.com — Vue frontends, Fastify APIs, PostgreSQL, background workers
  • Automated daily PostgreSQL dumps to object storage
  • Monitoring via Uptime Robot and PostHog

What I don’t self-host:

  • This blog — Jekyll on GitHub Pages, because it’s static and free
  • Email — transactional email goes through a service. Self-hosting email is a deliverability nightmare
  • CDN/edge — Cloudflare sits in front of the server for caching and DDoS protection

Getting Started

I wrote about the specific tools in detail:

The whole thing took about two days the first time. Subsequent projects take an hour or two — and most of that time is setting up API keys for external services, not the hosting itself. After that, every deploy is kamal deploy.