On a VPS You Cannot Tell What Is Overloaded

A SaaS founder told me his $20 server became a $600 monthly bill. The $20 machine had been fine for the first five years. After that, he increased its size for every burst of load. Once the load settled, shrinking it again was much harder than growing it, so it stayed big. Once he moved off the single machine onto separate services, with the database on its own, the bill came down to around $50 a month.

He ran everything on one virtual machine. A single virtual server running the web server, PHP and the database together is the most common setup I get asked to look at, and resizing the whole box is the most common fix.

Why the Whole Box Gets Resized

The resizing is a diagnosis problem. The web server and the database share the same processor and memory while competing for different things. PHP workers want memory and processor time. The database wants memory for its cache and fast disk access.

When the site slows down under load, the database usually looks guilty: connections pile up, queries queue, the processor is busy. And you cannot clear it, because its processor is the same processor the PHP workers are starving and its memory is the same memory they are filling. There are no separate figures to read.

A Common Pile-Up

A common pattern starts on the web side, as a loop:

  1. Individual PHP requests start taking longer.
  2. PHP starts more workers to keep up with the queue.
  3. Each worker reserves memory, and memory runs short.
  4. The workers take memory the database was using to cache data, which pushes the database onto the disk and slows its queries.
  5. Now every worker waits longer, so more pile up.

Each stuck worker keeps its database connection open while doing nothing with it. The database ends up with hundreds of open connections and looks overloaded while it is mostly waiting. The loop can start in either layer, and on a single box nobody can prove which. So the only fix anyone can justify is a bigger box.

What a Separate Database Tells You

Once the database runs on its own server, it has its own figures, recorded independently of everything else: processor use, read times, free memory, disk operations waiting.

If its processor is quiet and reads come back in about a millisecond while connections climb, the database is waiting, not working. The problem is on the web server, and that is where the fix and the money should go. A climbing connection count is also a useful early warning: it tends to rise before a pile-up on the web server is at its worst.

The Change I Usually Make

The change I usually make is smaller than the founder’s: move the database onto its own service, then size the web server for what it actually does. With the two separated, each can be measured and resized on its own, and the web server is often much smaller than the box it replaced. That usually halves the bill.

That is how we run our hosting: database, web server and CDN as separate services, each with its own figures and resized on its own.

What Separation Does Not Fix

Separation does not stop a web server from piling up. A busy web server shared by many sites can still run out of workers or memory. What separation changes is that you can prove where a slowdown started, rule out the database from its own figures, and put the fix on the web server instead of buying a bigger database you do not need.

Three Questions for Your Setup

  1. When your site last slowed down or fell over, could anyone say which part ran out? If the answer was “the server”, that is the single-box problem.
  2. Does your database have its own figures, separate from the web server’s? Processor, memory and disk use for each, recorded independently.
  3. Could you resize the database without resizing the web server? If not, every fix is a bigger box.

If you run a VPS and want to know which part of it runs out first, I am happy to look at its figures with you.

More Articles