Step 1 Understand it
The problem it solves. A system that works for 100 users can fall over at 100,000. You need a way to add capacity without rewriting everything.
New words in this topic (tap one to see what it means)
Watch it happen
Read the animation as text
- Vertical scaling: when one server is too slow, buy a bigger one — more CPU, more memory. Nothing else changes.
- Simple, and it often works for a long time.
- But there is a ceiling — the biggest machine you can buy — and it is still ONE machine. If it fails, everything is down.
Picture it
flowchart TD
LB["Load balancer"] --> S1["App server"]
LB --> S2["App server"]
LB --> S3["App server<br/>(added by auto-scaling)"]
S1 & S2 & S3 --> R[("Redis<br/>sessions")]
S1 & S2 & S3 --> P[("Database leader")]
P --> RR[("Read replica")]The idea
means a bigger machine (more and memory). It's simple, but there's a ceiling, and that one machine can fail. Horizontal scaling means more machines behind a load balancer. It has no hard ceiling and survives failures, but needs stateless app servers and shared storage. The key trick: keep app servers stateless, and keep sessions and data in shared stores.
How it works, step by step
- Find the first: is the CPU at 100%, the slow, memory full, or the network saturated?
- Make app servers stateless: no sessions or files kept on the server; put them in Redis and instead.
- Put a load balancer in front and add servers. With , servers are added automatically when CPU use or rises.
- Take reads off the database: hot data and add .
- When writes become the bottleneck, the database by a key.
- Move slow work off the path with .
Analogy
A busy restaurant can buy a bigger oven (vertical) or open more kitchens (horizontal).
Where the analogy breaks
More kitchens only help if any kitchen can cook any order. If half of a customer's order is in kitchen 2, it has to go back there. That's 'state', and it's why app servers should be stateless.
Example
Moving login sessions from server memory into Redis lets any server handle any user, so you can add servers freely.
Must-know points
- Stateless app servers plus a shared session store = easy horizontal scaling.
- Databases are the hard part: read replicas for more reads, sharding for more writes.
- Scale the real bottleneck: measure first (CPU, memory, database, network).
- Auto-scaling adds and removes servers based on load.
- is not speed: a system fast for one user can still collapse under many.
Common mistakes
- Adding app servers when the database is the real bottleneck.
- Keeping sessions in server memory, then adding more servers.
- Sharding far too early: it adds a lot of complexity.
Trade-offs
- Vertical: simple, no code changes, but a ceiling and a .
- Horizontal: almost unlimited and , but needs statelessness, load balancing and distributed data.
Step 2 Go further (free, optional)
Optional. The notes above are written to be enough on their own. These free resources give a second explanation and extra practice.
-
Watch
ByteByteGo: vertical vs horizontal scaling
ByteByteGo · YouTube
-
Read
Hello Interview: scale from zero to millions of users
hellointerview.com · free guides
-
Read
Donne Martin · GitHub, free
Step 3 Practise
Try each exercise yourself first: on paper, out loud or in code. Then open the answer and compare it with yours.
-
ExplainSay it in plain words in under a minute, with no notes.
Explain vertical and horizontal scaling with the restaurant picture.
Show answer
A busy restaurant has two ways to cook more meals.
Vertical scaling is buying a bigger oven: one machine with more CPU and memory. It is simple (nothing about how the kitchen works changes), but there is a biggest oven you can buy, and if that one oven breaks, nobody eats.
Horizontal scaling is opening more kitchens: more machines behind a load balancer. There is no hard limit, and if one kitchen closes the others keep cooking. But it only works if any kitchen can cook any order. If half of a customer's order is sitting in kitchen 2 (state, like a session kept in one server's memory), their next request has to go back there. That is why app servers are made stateless, with sessions and files kept in shared stores.
-
DrawSketch the diagram (or class diagram) from memory.
Draw a stateless app tier behind a load balancer, with a shared session store and a database with replicas.
Show answer
The app servers are identical and keep nothing between requests, so the load balancer can send any user to any of them, and auto-scaling can add or remove one at any time. All state lives below them: sessions in Redis, data in the database, where the takes writes and the replicas serve reads.
textClients │ Load balancer ┌────────┼────────┐ ▼ ▼ ▼ App App App ← stateless, server server server auto-scaled │ │ │ ├────────┴────────┤ ▼ ▼ Redis (sessions) Database leader ── writes │ copies changes ┌─────┴─────┐ ▼ ▼ Replica Replica ── reads -
ApplyUse it in a real design question and say exactly where it fits.
An app saves uploaded files on each server's local disk. Explain what breaks when you add a second server, and fix it.
Show answer
What breaks: a user uploads a photo and the load balancer sends that request to server 1, which saves it on its own disk. Their next request, "show my photo", goes to server 2, which has never seen the file: a broken image or a 404. It looks random, because it depends on which server you happen to hit. And if server 1 dies or is replaced, its files are gone for good.
The fix: keep no files on the app servers. Store uploads in shared object storage (such as Amazon ), and save only the file's key in the database. Better still, have the server hand the a short-lived signed upload URL, so the file goes straight to object storage and never passes through the app server at all. Serve files to users through a in front of the storage.
Now every server sees the same files, any server can handle any request, and you can add or remove servers freely.
-
Trade-offsSay what it costs, when not to use it, and the alternative.
Give one case where you'd scale vertically first, and why.
Show answer
The main database of a growing product, early on.
Say the primary is running out of CPU at 5,000 queries a second. Moving it to a machine twice as big takes an hour and needs no code changes. Sharding it means choosing a , rewriting the queries that across shards, moving the data and running many databases: weeks of work and a permanent increase in complexity.
Modern machines are huge (hundreds of cores, terabytes of memory), so vertical scaling can carry a database a long way. Do it first, together with the cheap horizontal steps around it (a cache, read replicas), and plan the sharding path for when the biggest machine is no longer enough. Also: keep a replica, because one big machine is still a single point of failure.
Step 4 Interview-ready, then prove it
Your interview answer
About 20 to 40 seconds, said out loud. Practise it until it sounds like you, not like notes.
I'd keep the application tier stateless so it scales horizontally behind a load balancer with auto-scaling. State goes into shared stores: sessions in Redis, data in the database. For the database, I'd add read replicas first and shard only when write volume needs it.
Follow-up questions
When is vertical scaling the right answer?
Early on, or for a database that's hard to split. It's simple and modern machines are very large. Just plan the horizontal path for later.
What makes a server ''?
It keeps data that later requests depend on, like a session in memory or an uploaded file on its local disk.
Tick each check when you can do it without notes
A topic is finished when you pass all four checks, not when you finish a video. Be strict: if you needed your notes, it is not ticked yet.
- Explain Say it in plain words in under a minute, with no notes.
- Draw Sketch the diagram (or class diagram) from memory.
- Apply Use it in a real design question and say exactly where it fits.
- Trade-offs Say what it costs, when not to use it, and the alternative.
0 of 4 checks ticked.
Saved in this browser. Back it up or move it to another device.