Home › High-Level Design › Scalability: Vertical vs Horizontal
S

Scalability: Vertical vs Horizontal

Almost every system design interview turns into a scaling conversation at some point. You sketch a clean design, the interviewer nods, then watches your app get popular and asks what you do when one box can no longer keep up. If you can reason clearly about going bigger versus going wider, with numbers instead of definitions, you have already shown half of what they want to see. I have sat on both sides of that table, so here is how I actually think about it.

High-Level DesignBeginner9 min read

If you remember five things

The whole topic in one glance. Everything below is the defense of these five calls.

  1. Up vs out. Vertical means one beefier box. Horizontal means more boxes behind a load balancer. The real choice is where you sit on each axis, not either/or.
  2. The ceiling is real. Vertical hits a hard wall (there is no server with a million cores) and gives you a single point of failure. Horizontal scales effectively without limit.
  3. Statelessness is the price of going wide. Any request must be able to hit any server, so sessions and local caches move out to Redis, object storage, or the database.
  4. Fault tolerance is the clincher. One big box rebooting takes everyone down. Lose one of seven boxes and you lose about 14% of capacity and zero uptime.
  5. The database is the next wall. Spreading the stateless tier is easy. The shared state behind it (one primary) is where the hard scaling problem actually moves.

1The core idea#

Scalability is just a system's ability to take on more load without falling over: more users, more requests per second, more data. The question is never "will traffic grow," it is "when it does, what do I change?" There are two answers.

Vertical scaling (scaling up): give one machine more muscle.

  • More CPU cores, more RAM, faster disks, same single server, just beefier.
  • Think moving from a 4-core box with 16 GB of RAM to a 64-core monster with 512 GB.
  • Your code and architecture do not change.

Horizontal scaling (scaling out): add machines and spread the work.

  • Instead of one giant server, run ten modest ones behind a load balancer.
  • Each handles a slice of the traffic.
  • Growth becomes "add another box," not "buy a bigger one."

The mental model I give juniors. Your restaurant is slammed:

  • Vertical scaling is hiring one superhuman chef who cooks four times faster. Simple to manage, but there is a ceiling on how fast any human gets, and if that person calls in sick, you are closed.
  • Horizontal scaling is hiring four normal chefs and splitting the orders. They need coordination, but you can keep adding cooks, and losing one just slows you down a bit.

Simplicity plus a hard ceiling, versus coordination plus near-limitless growth. That trade is the whole topic.

2How it works#

Vertical scaling is mechanically boring, which is a compliment.

  • You resize the instance. On AWS that is often changing m5.large to m5.4xlarge and rebooting.
  • Code does not change. Architecture does not change.
  • The server comes back with more resources and serves more concurrent requests. Done.

Horizontal scaling is where the interesting engineering lives. You cannot just clone a server and hope. Something has to sit in front and decide which copy handles each request. That is the load balancer.

  • A request comes in, the balancer picks a healthy server (round robin, least connections, whatever policy you set), and forwards it.
  • If one server dies, the balancer stops sending it traffic.
  • Add a server, the balancer starts using it.
flowchart LR A[Client] --> B[Load Balancer] B --> C[Server 1] B --> D[Server 2] B --> E[Server 3] C --> F[(Database)] D --> F E --> F C --> G[(Cache)] D --> G E --> G
Three servers, but they all talk to one database and one cache. That shared state at the bottom is the catch nobody mentions at first: spreading the web tier out is the easy part, and the state behind it is what makes horizontal scaling hard.
The point of this section

Fanning out the web tier is the move everyone remembers. The thing that earns points is naming what it does not solve: the database and cache under those boxes are still single, shared, and now taking the combined load of every server you added. Horizontal scaling moves the bottleneck, it does not delete it.

For this to work cleanly, your servers must be stateless.

  • No request should depend on landing on the same machine as a previous one.
  • If server 2 holds a user's login session in local memory and the next request routes to server 3, that user is suddenly logged out.
  • So you push shared state out of the app servers into a place all of them reach: a session store like Redis, a shared cache, the database.

Get statelessness right and scaling out becomes almost mechanical.

  • Traffic doubles, you double the servers.
  • That is the dream, and it is achievable. It just takes discipline up front.

3A worked example with real numbers#

Abstract trade-offs convince no one. Here is a concrete capacity calculation, the kind I would sketch on the whiteboard. Say we are building the API tier for a product that just hit 10 million daily active users.

Getting to the peak number.

  • Each user makes about 20 API calls a day, so 200 million requests per day.
  • Spread over 86,400 seconds, the average is roughly 2,300 requests per second.
  • Traffic is never flat. Peak is usually 3x to 4x average, so design for 9,000 RPS at peak with headroom.

The single-box plan.

  • A beefy m5.4xlarge (16 vCPU, 64 GB) running a tuned Node or Go service handles maybe 2,000 RPS before p99 latency climbs past 200 ms.
  • To hit 9,000 RPS on one box you need roughly 4.5x that capacity.
  • The next steps up are m5.12xlarge and m5.24xlarge (96 vCPU, 384 GB), the top of that family.
  • The 24xlarge gets close to the ceiling of the line and costs about $4.60 per hour on-demand, roughly $3,300 a month, for one server with zero redundancy.
  • If it reboots, 10 million users see errors.

The horizontal plan.

  • Take the same m5.4xlarge at about $0.77 per hour doing 2,000 RPS.
  • To serve 9,000 RPS you need 5 of them, and you run 7 to carry one failure and leave headroom.
  • That is 7 x $0.77, about $5.40 per hour, roughly $3,900 a month.
  • Slightly more than the giant box, but losing one server now costs 1/7 of capacity (about 14%) and zero downtime.
  • You can go to 14 boxes for Black Friday by lunchtime, then scale back down at night. The single-box plan has no such move left: it was already near the top of the instance line.
~14%
The number that settles itLosing one box in a 7-box fleet costs about 14% of capacity and zero downtime, drained in one health-check interval (often under 10 seconds). Losing the single big box is 10 million users down for the 60 to 120 seconds it takes to reboot. Same monthly spend, wildly different blast radius.

4Trade-offs#

This is the part interviewers care about most. Anyone can define the terms. Can you reason about what you give up?

Dimension Vertical (scale up) Horizontal (scale out)
Complexity Low. Resize and reboot. Higher. Load balancer, stateless design, coordination.
Ceiling Hard. Biggest box you can buy. Effectively unlimited. Keep adding nodes.
Fault tolerance Weak. One box, one failure. Strong. Lose a node, others carry on.
Downtime to scale Usually a reboot. Add nodes live, no downtime.
Cost curve Climbs steep at the high end. More linear, but more moving parts.
Code changes None. Often needed (sessions, locality).

A few of these deserve real talk.

The ceiling is real and closer than you think.

  • The largest cloud instances today top out in the low thousands of GB of RAM and a few hundred vCPUs.
  • In the worked example, I was already brushing the top of the m5 line just to serve 9,000 RPS on one box.
  • That sounds like room until your product hits the front page and traffic goes 50x overnight.
  • You cannot buy your way past physics. There is no server with a million cores.

Cost is not linear when you scale up.

  • Doubling a small instance is cheap. At the top end, each step up costs more than the capability it adds.
  • In the example, the 24xlarge was 6x the price of the 4xlarge for roughly 5x the vCPUs, and it handed me a single point of failure on top.
  • The jump from a large box to a huge one often costs 3x for maybe 2x the throughput.
  • A fleet of commodity boxes usually gives you more compute per dollar past a certain size, plus the resilience comes free.

Fault tolerance is the one I would lead with.

  • A single scaled-up server is a single point of failure, and hardware does die.
  • When it dies, your whole service is down until it reboots or you fail over.
  • With 7 servers, losing one costs about 14% capacity and zero downtime.
  • For anything users depend on, this alone often decides it.
From the interviewer's chair

I am not listening for which one is "right." I am listening for whether you say the quiet part out loud: in practice you do both. Pick a reasonably sized instance (vertical) and run several behind a load balancer (horizontal). Candidates who treat this as a spectrum of trade-offs, not a multiple-choice question with one correct box, read as people who have actually run systems.

5Where it is used#

Vertical scaling shows up where splitting the workload is genuinely hard.

  • The classic case is a traditional relational database. Sharding a Postgres or MySQL primary across machines is painful: joins across shards, transactions that span shards, rebalancing data, all nightmares.
  • So the common move is to scale the database up as far as you reasonably can, and only shard when truly forced to.
  • You also see vertical scaling early in a product's life, when you have a handful of users and adding architectural complexity would be a waste of time.

Horizontal scaling is the default for stateless web and application servers.

  • API backends, web frontends, worker queues: built to run as many identical copies.
  • Big consumer services run thousands of app server instances, all interchangeable.
  • It is also how distributed databases like Cassandra, DynamoDB, and modern object stores are built from the ground up: add nodes, get more capacity and more resilience.

My rule of thumb.

  • Scale the stateless tier horizontally without a second thought.
  • Scale the stateful tier vertically for as long as you can get away with it, before you are forced into the harder work of partitioning data.

6Common pitfalls and gotchas#

Storing session state on the app server.

  • The number one reason horizontal scaling breaks: login sessions, uploaded files, in-memory caches living on individual boxes.
  • The fix is to externalize state: sessions in Redis, files in object storage, cache in a shared layer.
  • Design stateless from day one and your future self will thank you.

Forgetting the database is still shared.

  • I have watched candidates add ten web servers, declare victory, and never notice every one of them hammers a single database.
  • In the worked example, 7 app servers at 9,000 RPS still point at one Postgres primary. You just moved the bottleneck.
  • Now the database is the wall. The data tier needs its own plan: read replicas, caching, eventually sharding.

Treating "scalable" as "infinite and free."

  • More nodes means more network calls, more coordination, more things that fail independently, and a bigger bill.
  • Distributed systems have real overhead. Do not scale out a system a single right-sized box would serve happily.

Ignoring the sticky-session crutch.

  • Some teams patch the stateless problem by pinning each user to the same server (sticky sessions).
  • It works until that server dies and takes those users' state with it, and it makes load uneven.
  • It is a band-aid, not a design.

Over-engineering for scale you do not have.

  • The flip side. 200 users do not need a multi-region auto-scaling fleet.
  • Interviewers notice when you reach for complexity the problem does not justify. Scale when the numbers tell you to.
Red flag that fails you here

Answering "I would use a bigger server," full stop. It shows you do not see the ceiling or the single point of failure. When I push with "what happens when that box reboots?", there is no reply, because the whole service is down and there is no bigger box left to buy. Reach for horizontal and a load balancer on your own.

7How it shows up in interviews#

The scaling question almost always arrives the same way. You sketch a clean design, the interviewer nods, then says: "Great. Now it is 10 million users a day. What changes?"

Pause before you read on: you have added 7 stateless web servers behind a load balancer. The interviewer looks unimpressed and asks "what did that actually fix?" What is the honest answer?
Reveal the answer
It fixed the web tier: capacity and fault tolerance for stateless request handling. It did not fix the database. All 7 servers still point at one primary, so you moved the bottleneck down a layer, you did not remove it. The strong candidate names this before being asked and pivots to read replicas, a cache, and sharding only if write volume forces it.

What they are probing.

  • Do you reach for horizontal scaling and a load balancer naturally?
  • Do you understand why the app servers must be stateless, not just that they should be?
  • Do you notice the database becomes the next bottleneck?
  • Can you weigh cost, failure, and complexity with real numbers instead of reciting definitions?

What the answers sound like at each level.

Fails
"I would use a bigger server."
Capacity math
None.
Ceiling
Unseen. No reply when the box reboots.
Database
Never mentioned.
Signal
Has not hit the single-point-of-failure wall in real life.
Strong
"7 stateless boxes, then the DB is the wall."
Capacity math
2,300 RPS average, ~9,000 at peak, from first principles.
Ceiling
Named: one box fails, lose ~14%, zero downtime.
Database
Flagged as the next bottleneck: replicas, cache, shard later.
Signal
Treats it as a spectrum of trade-offs, not a single right box.

The strong answer, spelled out. "At 10 million daily users with roughly 20 calls each, that is about 2,300 requests per second average, call it 9,000 at peak. I would scale the web tier horizontally behind a load balancer, say 7 mid-size instances so one can fail with no downtime, and keep those servers stateless so sessions live in Redis and any request can hit any server. That gives me both capacity and fault tolerance, since losing one box just costs about 14% of throughput. The next bottleneck becomes the database, because all 7 app servers still point at one primary. I would add read replicas for read-heavy traffic and put a cache in front of it. For the write path I would scale the primary vertically for now, and only shard if write volume outgrows the biggest instance, because sharding adds real operational pain. Early on, when traffic is small, I would keep it simple with one decent instance and not pay the complexity cost until the numbers demand it."

That answer hits every axis: a capacity estimate from first principles, horizontal for stateless, vertical where partitioning is hard, the shared-state trap, the database as the real wall, and the judgment to not over-build.

Follow-ups the interviewer will ask (and your answers)
"You added 7 web servers. What happens when the database can't keep up?"
That is the bottleneck moving, not disappearing. I add read replicas for read-heavy traffic, put a cache (Redis) in front for hot reads, and scale the primary vertically for the write path. Sharding comes last, only when write volume outgrows the biggest single instance, because partitioning brings cross-shard joins and transaction pain.
"A user logs in, then their next request gets a different server and they're logged out. Why?"
The session was stored in that first server's local memory, so it does not exist on the second. The fix is statelessness: push sessions into a shared store like Redis so any server can serve any request. Sticky sessions can mask it, but they break when that server dies and they skew load, so they are a band-aid, not the design.
"Same monthly cost either way. Why not just buy the one giant box?"
Blast radius. The giant box is a single point of failure: a reboot is 10 million users down for 60 to 120 seconds, and I am already near the top of the instance line with nowhere left to grow. The 7-box fleet drains a dead node in one health-check interval, loses about 14% capacity, and I can double it for a traffic spike and shrink it back later.
"When would you actually prefer vertical scaling?"
When splitting the workload is genuinely hard, which usually means the stateful tier. I scale a relational primary up as far as it goes before sharding, because sharding is operationally painful. I also scale up early in a product's life, when traffic is tiny and adding a distributed architecture would be wasted complexity.
"How did you get 9,000 RPS without a load test in front of you?"
First principles. 10 million daily users times ~20 calls is 200 million requests a day, over 86,400 seconds is ~2,300 RPS average. Real traffic is spiky, so I apply a 3x to 4x peak multiplier and design for ~9,000 with headroom. The interviewer wants to see the estimate reasoned out, not a memorized figure.

What you can now explain in the room

  • The difference between scaling up and scaling out, and why the real choice is where you sit on each axis.
  • Why vertical scaling hits a hard ceiling and leaves you with a single point of failure.
  • Why horizontal scaling demands stateless servers, and where shared state has to live instead.
  • How to derive ~2,300 RPS average and ~9,000 at peak from 10 million daily users.
  • Why same-cost plans can have wildly different blast radius (one reboot vs losing 14%).
  • Why the database is the next wall, and the order of fixes: replicas, cache, then shard.

Next, try the System Design Question walkthrough on designing a URL shortener, where this exact vertical-versus-horizontal decision plays out across the web tier, the cache, and the data store.

Get a prep plan built around your Scalability: Vertical vs Horizontal interview

Tell us the role and your interview date. We will send back a dated, day by day plan. Free.

Thanks. Check your inbox, your Scalability: Vertical vs Horizontal prep plan is on the way.