Before the first customer, the hosting decision is reversible and cheap. The question is not which platform is best but how much of the stack you should operate yourself while nobody is depending on it.

The Case for One Server

A single virtual machine with 2 vCPU and 4 GB of RAM costs roughly $20 to $25 a month and will serve a pre-revenue SaaS with room to spare. It runs the application process, a reverse proxy, and a local Postgres instance without contention. At ten concurrent users you are using a few percent of it.

The real benefit is not price. It is that one machine has one log location, one deploy target, and one place where state lives. When something breaks at 11 p.m. you are reading one file, not correlating three dashboards.

What Not to Run Yourself

Two categories should go to a managed provider immediately regardless of scale: anything that stores the only copy of customer data, and anything that handles credential material.

Self-hosted Postgres is fine on day one, but only with an automated off-box backup you have restored from at least once. If you cannot describe your restore procedure in three sentences, pay the $15 to $30 a month for managed Postgres and delete the problem. The same applies to outbound email: run your own SMTP and you inherit deliverability, reputation, and DNS debugging as permanent side work.

The Failure Mode Nobody Plans For

The most common one-server incident is not traffic. It is a full disk. Logs accumulate, a database vacuum needs temporary space, and the application starts throwing write errors that look like application bugs.

Two lines of prevention: cap log retention at 7 days with logrotate, and set an alert at 80 percent disk usage. That single alert catches the majority of avoidable pre-launch outages. The second most common is a process that dies and never restarts, which a systemd unit with Restart=always resolves permanently.

When One Server Stops Being the Answer

There are three concrete signals, and none of them are user count. The first is a deploy that causes visible downtime you cannot schedule, because your users are now in more than one timezone. The second is a background job that competes with request handling for CPU, showing up as p95 latency that spikes on a cron schedule. The third is a compliance answer you cannot give, such as where backups are stored and who can access them.

Any one of those justifies splitting the workload. Absent all three, adding a load balancer, a container orchestrator, and a separate job runner buys you configuration surface and nothing else.

A Reasonable Starting Shape

One VM running the app under a process supervisor. A managed database with daily backups. Object storage for user uploads, because local disk uploads are the hardest thing to migrate later. TLS from the reverse proxy with automatic renewal. Deploys from a single script that pulls, builds, and restarts.

That configuration takes an afternoon to set up, costs under $50 a month, and will carry you to the first few thousand dollars of monthly revenue. The migration off it, when it comes, will be driven by a specific constraint you can name — which is the only good reason to do infrastructure work at all.

Get articles like this by email

Production patterns, checklists, and failure stories for people shipping SaaS. No spam.