800 requests/scan serve 1,000
- Ride server 18 vCPU
- Ride server 28 vCPU
- Ride server 38 vCPU
- Ride server 48 vCPU
- Ride server 58 vCPU
- Ride server 68 vCPU
- Ride server 78 vCPU
- Ride server 88 vCPU
800 requests/scan serve 1,000
800 requests/scan serve 1,000
8 vCPU · 32 GB
Uber on a Friday night: add more machines, or buy a bigger one? Illustrative numbers: one 8-vCPU server handles about 1,000 ride requests a second.
Scale up while it’s easy — databases often do first. Scale the stateless parts out, and plan for machines to die.
| Difference | Horizontal | Vertical |
|---|---|---|
| How you grow | Add copies behind a load balancer | Move to a bigger machine |
| Ceiling | Practically none: keep adding copies | The largest machine you can get |
| Downtime to grow | None: new copies join while traffic flows | Usually a restart to resize |
| When a machine dies | The health check routes around it | Everything is down until it’s back |
| Cost | Add and remove copies as traffic moves | Sized for the peak, since resizing means a restart |
| What it needs | Servers that keep no session: state lives in Redis or the database | Nothing new in the code |
| Typical use | Stateless app servers, like Uber’s Ride service | Databases, before read replicas or sharding |
Friday night on Uber, and ride requests keep coming. There are two ways to handle more traffic. On the left, horizontal scaling: add more servers. On the right, vertical scaling: one bigger server. Let’s put both through four situations.
First, a normal evening: eight hundred requests a second. One server behind the load balancer handles it. In this example, one server can serve about a thousand a second.
On the right, one eight-core server copes just as well.
Next, rush hour. Requests jump to three thousand two hundred a second, far more than one server can serve, so they start to queue.
Horizontal scaling adds three more servers. The load balancer sends them requests straight away, with no downtime. Four servers now serve four thousand a second.
On the right, rush hour overwhelms the single server.
To scale up, it moves to a bigger machine with thirty-two cores. But resizing means a restart, and while it restarts, nobody gets a ride.
When it’s back, it serves four thousand a second, but only after an outage.
Then New Year’s Eve: seven thousand two hundred requests a second.
Horizontal scaling simply adds four more servers. Eight servers, eight thousand a second, and room for more.
Vertical scaling has to grow again.
It moves to sixty-four cores, the largest machine available, through another restart and another outage.
It copes tonight, but next time there’s no bigger machine to move to.
Finally, a server dies. Server three crashes, and for a moment the load balancer still sends it requests, which fail.
Its health check fails, so the load balancer stops sending it traffic, and the other seven carry the load.
A replacement starts automatically, and no rider ever sees an error.
On the right, there is only one machine. When it crashes, every request fails.
Every rider sees an error until it comes back. One machine means one point of failure.
So which should you pick? Scaling up is simple, and it’s often the first step for a database. But for app servers, scale out: add servers behind a load balancer, and plan for machines to fail.