DevTools Hub

Search tools

Search for a developer tool

Horizontal vs Vertical Scaling

Part of the Scalability Toolkit

Vertical scaling makes one machine bigger. Horizontal scaling adds more machines instead. That one-sentence definition is where most explanations stop — the actually useful part is why each one is the right call in genuinely different situations, and it comes down to a single question neither approach can dodge: does this thing hold state?

Vertical — before
1 instance
app + db4 vCPU, 16 GB
Vertical — scaled up
still 1 instance
app + db64 vCPU, 512 GB
Horizontal — scaled out
4 instances behind a load balancer
instance 14 vCPU, 16 GB
instance 24 vCPU, 16 GB
instance 34 vCPU, 16 GB
instance 44 vCPU, 16 GB

Vertical scaling keeps one machine — and one point of failure — and makes it bigger. Horizontal scaling keeps machines the same size and adds more of them, each individually disposable.

Vertical scaling: simple, until it isn't

Vertical scaling — "scaling up" — means giving an existing machine more CPU, RAM, or faster storage. It requires no architecture changes: the application doesn't even need to know it happened. That simplicity is real and worth taking seriously as a first move, not a compromise — resizing a box is almost always less work than redesigning a system to run on many.

It has two hard limits. First, a literal ceiling: every cloud provider sells a largest instance size, and once a workload needs more than that, there is no bigger box to buy at any price. Second, an operational one that matters well before the ceiling: resizing a running machine usually means real downtime or a genuinely careful live migration — you can't add capacity to a single running box the way you can add a new one alongside it.

Horizontal scaling: no ceiling, but a coordination problem

Horizontal scaling — "scaling out" — adds more machines and spreads load across them with a load balancer. In principle there's no ceiling: keep adding instances. In practice, capacity planning for this is a direct, well-defined question — Throughput Calculator answers exactly it via Little's Law: given a target requests/sec and a latency, it computes precisely how many instances that load needs, and how much headroom a given instance count actually has.

Unlike a resize, adding an instance requires no downtime — bring the new one up alongside the existing ones, let the load balancer start routing to it, and retire an old one whenever convenient. That's the operational trade horizontal scaling makes for its added complexity: no single resize event, ever, but now there's more than one machine to keep consistent.

The question that actually decides which one you need: does it hold state?

A stateless web server handling independent requests is close to the ideal case for horizontal scaling — any instance can handle any request, so the load balancer can send a request anywhere and it doesn't matter which. Add an instance, and capacity goes up with essentially no coordination cost between instances.

A database is the opposite case, and it's the reason "just add more database servers" is nowhere near as simple as it sounds for a stateless tier. The moment there's more than one copy of the data, every write has to somehow reach every copy, and reads have to decide whether they can tolerate seeing a copy that hasn't caught up yet. This is exactly the trade-off the CAP theorem (Brewer, 2000; formally proven by Gilbert and Lynch, 2002) describes: during an actual network partition, a distributed system can guarantee consistency (every node sees the same data) or availability (every request gets a response), but not both at once. That's not an engineering shortfall to be fixed with better code — it's a proven result about what's possible at all. See CAP Theorem Explained for why "pick two of three" is actually the wrong way to remember this, and which real systems land on which side.

This is why databases usually scale vertically first, then horizontally in a specific, constrained order: read replicas (copies that only serve reads, tolerating slightly stale data) before sharding (splitting the data itself across machines, where a write to shard A never touches shard B) — because sharding is where the coordination problem gets genuinely hard, not optional.

Fault tolerance is the other axis, not just capacity

A vertically-scaled system has exactly one machine to lose. When it goes down, the service goes down with it, regardless of how much headroom that machine had — capacity and availability are the same number. A horizontally-scaled system with N instances can usually lose one and keep serving from the remaining N−1, assuming the load balancer detects the failure and routes around it — capacity drops, but the service doesn't disappear. That difference is frequently the actual reason a team scales out, even when a single bigger machine would have had plenty of raw capacity to spare. See Load Balancers Explained for exactly how "detects the failure and routes around it" actually works — it's not automatic, it's a specific, real mechanism.

What real systems actually do

Almost never purely one or the other. A typical setup: a stateless application tier scaled horizontally behind a load balancer (cheap to add capacity to, tolerates losing an instance), talking to a database that's scaled vertically up to a comfortable ceiling and horizontally only via read replicas — full sharding reserved for the point where a single primary genuinely can't keep up with write volume, because it's the most expensive, hardest-to-reverse step available.

Worth checking before scaling either direction: whether the bottleneck is actually a capacity problem at all. Database Index Cost Estimator and Understanding B-Trees cover the classic case where a "slow database" is a missing index, not a machine that's too small — scaling the hardware doesn't fix an algorithmic problem, it just makes it more expensive to have. Cache Hit Ratio Calculator covers the other classic first move: a well-placed cache can absorb enough load that neither scaling direction is needed yet at all.

FAQ

Does horizontal scaling require Kubernetes or containers?

No — it's an architectural principle (multiple instances behind a load balancer), not a specific technology. It works with plain VMs, containers, or bare processes; Kubernetes and similar orchestrators are just popular tools for automating the "add or remove an instance" part, not a requirement for the concept itself.

Is vertical scaling outdated?

No — treating it as an inherently inferior, legacy approach is itself a mistake. For a huge share of real systems, a bigger box is a correct, boring, low-risk answer that avoids distributed-systems complexity a team may not need yet. Scaling out before there's a real reason to just trades a simple problem for a harder one.

Can a stateful system ever scale horizontally without the CAP trade-off?

The trade-off only bites during an actual network partition — most of the time, a well-designed distributed database is both consistent and available, because most of the time nothing is partitioned. The theorem describes what has to give during a partition, not a permanent tax paid on every single operation.

Related tools