23 Oct 2026 · 4 min read · Ravi Sanchala
One server to four: what happened when we split a crashing VM
A fintech platform kept crashing on a single machine. Splitting it into four small, isolated servers fixed stability and security at the same time.
Most products start on one server. That’s not a mistake. When you’re validating an idea, one machine running the app, the database, the cache and a few internal tools is cheap and fast to set up.
The mistake is staying there after the product starts working.
I recently worked with a fintech client in exactly this spot. Their Go application, PostgreSQL, a cache and some internal tools all ran on one VM. At 80 to 100 transactions a day, the server hit high CPU, crashed, and customers saw timeouts. Today the same platform handles more than 1,000 transactions a day without drama. The fix wasn’t a bigger machine. It was more, smaller machines with one job each.
Why one big server fails in a specific way
When everything shares one machine, everything shares one failure.
- Resource fights. A slow query eats CPU, and the app stops answering. A burst of traffic fills memory, and the database gets killed. You can’t tell which part is the real problem, because they all degrade together.
- One door into everything. If the server is reachable from the internet, so is the database, the cache and the internal tools. A single misconfigured port exposes all of them.
- You can’t size anything properly. The database wants memory. The app wants CPU. The cache wants a bit of both. One instance type is a compromise for all of them.
Upgrading to a bigger instance buys time, but it keeps all three problems.
The four-server layout
Here’s the shape we moved to:
| Server | Job | Who can reach it |
|---|---|---|
| Gateway | Reverse proxy (Caddy), TLS | The internet |
| App | The Go binary, managed by systemd | Only the gateway |
| Database | PostgreSQL | Only the app |
| Cache | Valkey | Only the app |
Each layer accepts traffic only from the one in front of it. The gateway is the only machine with a public IP. Everything else lives on a private subnet.
What changed, piece by piece
The gateway became the only door. One machine faces the internet, so there’s one place to harden, one place to watch, and one place where TLS terminates. If you ever move clouds, you point DNS at a new gateway and nothing behind it needs to change.
The app got its own restricted user. The binary runs as a dedicated system user that can manage its own systemd service and nothing else. If the app is ever compromised, the blast radius is that one service, not the whole machine.
The database got split permissions. Separate users for reading and writing. Reporting tools and background jobs that only read get a read-only user. A bug in a read path can’t corrupt data.
The cache took load off the database. Rate limiting, user lookups and auth token checks moved to Valkey. Those are small, frequent reads that the database was doing thousands of times a day for no reason.
Each server got sized for its own job. Only the database runs on a larger instance. The gateway, app and cache run on small ones. You pay for what each part actually needs.
“Isn’t four servers more expensive?”
Sometimes, yes. Four small instances can cost more than one medium one, depending on the provider’s prices.
I don’t sell this as a cost cut, and you should be suspicious of anyone who does without showing you the bill. What you’re buying is:
- A crash in one part that doesn’t take down the others
- A database that isn’t reachable from the internet
- The ability to scale the one part that’s actually under pressure
- Clear logs and metrics per role, so debugging is faster
For a platform that handles money, that’s usually an easy trade.
How to know you’ve outgrown one server
You probably need to split if:
- You’ve already upgraded the instance once “to fix performance”
- You can’t tell whether a slowdown is the app or the database
- Your database port is reachable from anywhere other than your app
- A deploy or restart means everything goes down together
- You’re nervous every time traffic spikes
If three or more of those sound familiar, the split is worth planning now, before the next crash plans it for you.
Do it as code, not by hand
The last piece matters as much as the architecture: build the new layout with infrastructure as code. Servers, networks and firewall rules defined in files, reviewed before they’re applied. That way the new setup is documented by default, and you can rebuild any of the four servers without guessing how it was configured.
Boring architecture. Boring results. That’s the goal.