Start

Course · 01

How do you size a system before you build it?

This page teaches the base words and the quick maths every system design interview uses: how systems grow, how fast they answer, how often they break, and how to guess their size on a whiteboard.

TL;DR

System design is about trade-offs, and you need a few numbers and words to talk about them.

  • Grow by adding more machines (horizontal), which only works if the servers keep no memory of users (stateless).
  • Judge speed by percentiles like p99, not averages. If each server is slow 1% of the time, fanning out to 100 of them makes 63% of requests slow.
  • Each extra "nine" of availability cuts allowed downtime by 10x: 99.99% is 52.6 minutes a year.
  • Estimate with round numbers: a day is about 100,000 seconds, so QPS ≈ requests per day ÷ 100,000.
86,400
seconds in one day (round to 10⁵)
52.6min/year
downtime allowed at 99.99% (Google SRE book)
63%
requests slow when fanning out to 100 servers with a 1% slow tail

—Words you need

Every hard word on this page, in plain words glossary

Scale
Handle more users or data without breaking or slowing down.
Node / instance
One running server machine (real or virtual).
Load balancer
A traffic cop that sends each request to one server.
Stateless
The server forgets you after each request. Any server can answer.
Latency
How long one request takes, start to finish.
Throughput
How many requests finish per second.
QPS / RPS
Queries (requests) per second. The usual load number.
Percentile (p99)
99% of requests were this fast or faster.
Tail latency
The slowest few requests, like the worst 1%.
Availability
Share of time the system works for users.
SLI / SLO / SLA
What you measure / the target / the paid promise.
SPOF
Single point of failure: one part whose death kills everything.
Redundancy
Spare copies, so one failure is not an outage.
DAU
Daily active users: people who use the app on a day.
Back-of-the-envelope
Rough maths with round numbers, done in two minutes.

Scale

01What a system design interview tests

It is a conversation about trade-offs, not a quiz core

You get a vague task like "design Instagram". There is no single right answer. The interviewer watches how you think.

For an SDE-2 (a mid-level engineer), they look for four things. Can you ask good questions first? Can you draw a working design? Can you size it with numbers? Can you explain why you picked each part, and what it costs?

SignalWhat a strong answer showsWhat a weak answer shows
RequirementsAsks about users, features, scale, speed goals before drawingStarts drawing boxes in minute one
EstimationTurns users into QPS, storage and bandwidth with round numbersSays "it needs to scale" with no numbers
High-level designSimple boxes that work end to end firstKafka, Redis and microservices with no reason
Deep diveGoes deep on the hardest part (hot keys, consistency, fan-out)Stays shallow everywhere
Trade-offs"I pick X because Y; it costs Z""X is the best"
In everyday words
It is like an architect meeting a client. They ask how many people will live in the house before they draw the walls.
Actually
There is no official rubric that all companies share. The four signals above are common practice, not a standard. Page 15 walks through the full interview framework. The numbers part (estimation) is taught in this page, sections 10 and 11. This rubric is not proven from any official source; it is how most tech companies describe their loops.

Every later page gives you parts. This page gives you the words and numbers to argue about them.

Source: common interview practice (no official spec). See page 15 of this course.

02Vertical vs horizontal scaling

Buy a bigger machine, or buy more machines core interview favourite

Vertical scaling (scale up) means a bigger machine: more CPU, more memory. It is simple. But one machine has a size limit, and it is still one machine that can die.

Horizontal scaling (scale out) means more machines of the same size. A load balancer (a traffic cop) spreads requests across them.

Horizontal scaling behind a load balancer Users send requests to a load balancer, which spreads them across three identical servers. HTTP Usersapps, browsers Load balancerspreads load Server 1 Server 2 Server 3 LEGEND Key part Same server, copied Callers
Scale out: add Server 4 and the load balancer starts using it.
QuestionVertical (scale up)Horizontal (scale out)
How you growBigger CPU, more RAM, faster diskMore machines behind a load balancer
Code changesNo, usually noneYes: servers must be stateless
Upper limitThe biggest machine you can buyVery high, until a shared part (often the database) is the bottleneck
FailureOne machine = one point of failureOne dies, the others carry on
Cost curveBig machines cost more per unit of powerMany small, cheap machines
Good first step forDatabases, early-stage appsWeb and API servers
In everyday words
A busy shop can hire one super-fast cashier (vertical) or open more checkout lanes (horizontal). More lanes need a greeter to send people to free lanes.
Actually
Microsoft's Azure Architecture Center says to "design your application so that it can scale horizontally, adding or removing instances". It also warns: "if your backend database is the bottleneck, it won't help to add more web servers", and "stateful parts of the system are the most likely cause of bottlenecks". Source: Azure: Design to scale out.

In an interview, scale web servers out, and say clearly what you do about the database, because that is where scale-out stops.

Source: learn.microsoft.com · Design to scale out (checked 2026-10-25)

03Stateless vs stateful services

Where does the user's data live between requests? core

State is data a server remembers between requests, like "who is logged in" or "what is in the cart".

A stateful server keeps it in its own memory. Then the user must always come back to that same server. This is called a sticky session.

A stateless server keeps nothing. It reads state from a shared store, like Redis (a fast in-memory database). Any server can answer any request.

Stateless servers with a shared session store Users go through a load balancer to server A or server B; both servers read session data from one shared store. Users Balancerany server Server Ano memory Server Bno memory Shared storee.g. Redis LEGEND Stateless server Where state lives State read
The servers hold nothing. The state moved into one shared store.
In everyday words
A stateful waiter remembers your order in their head, so only they can serve you. A stateless waiter writes it on a ticket at the counter, so any waiter can bring your food.
Actually
The Twelve-Factor App guide says: "Twelve-factor processes are stateless and share-nothing", and "Sticky sessions are a violation of twelve-factor and should never be used or relied upon". It suggests keeping session data in a store with expiry, such as Memcached or Redis. Azure lists "storing session state in memory" as a cause of stickiness that "limits the application's ability to scale out". Note: the state did not disappear. It moved to the store, which now must itself scale and stay up. Sources: 12factor.net/processes, Azure scale-out guide.
Part of the systemUsuallyWhy
Web / API serversStatelessEasy to add, remove and restart
Databases, caches, queuesStatefulTheir whole job is to keep data; scale them with replication and sharding (page 07)
WebSocket / game serversStateful (live connection)A live connection is tied to one machine; route by user ID

Push state down into a few special stores. Keep everything above them stateless, so it can scale out freely.

Sources: 12factor.net · VI. Processes; Azure Architecture Center · Design to scale out

Speed

04Latency vs throughput

How long one request takes vs how many finish per second core

Latency is time for one request, in milliseconds (ms). Throughput is work done per second, like requests per second (RPS) or MB per second.

They are linked but not the same. You can raise throughput by doing many requests in parallel, while each one is still slow.

In everyday words
A highway: latency is how long your drive takes. Throughput is how many cars pass per hour. Adding lanes raises throughput. It does not make your own trip shorter.
You wantTypical toolsCost
Lower latencyCache, CDN close to users, fewer network hops, indexesMore memory, stale data risk
Higher throughputMore servers, batching, async queues, parallel workBatching and queues often add latency
Actually
When a server gets busy, requests wait in a queue. Waiting time grows fast as the server nears full use. So pushing throughput close to the limit makes latency jump. Little's Law (section 06) ties the two together exactly: requests in flight = throughput × latency. The "latency grows near full use" claim is classic queueing theory; this page does not prove the exact curve (not proven here).

Always say which one you are optimising. "Fast" is not a requirement; "p99 under 200 ms at 10,000 RPS" is.

Source: Little's law; see section 06.

05Percentiles and tail latency

Why p99 matters more than the average deep dive interview favourite

Sort all request times from fast to slow. p50 (the median) is the middle one. p95 is the one where 95% are faster. p99: 99% are faster.

The tail is the slow end, above p99. An average hides the shape. It can say 30 ms when 1 user in 100 waited 2 seconds.

The tail gets worse with fan-out: one user request that calls many servers at once. The user waits for the slowest one.

Fan-out makes tail latency common One user request goes to a front end, which calls many leaf servers in parallel and must wait for the slowest one. 1 ASK Userone search Front endwaits for all Leaf 1usually 10 ms Leaf 2usually 10 ms … Leaf 1001% take 1 s LEGEND Waits for the slowest Leaf server (100 of them)
The front end is only as fast as its slowest leaf.

Chance a user request is slow, by fan-out size

Each server is slow (1 s) on 1% of calls. Chance = 1 − 0.99ⁿ. Hover a row for the exact number.

1 server
1.0%
10 servers
9.6%
100 servers
63.4%
Show the full table
Servers called in parallel (n)Chance at least one is slow
11.0%
109.6%
10063.4%
In everyday words
A group dinner where the table is served only when every dish is ready. One slow cook out of a hundred holds up the whole table.
Actually
Dean and Barroso's paper "The Tail at Scale" (Communications of the ACM, 2013) gives this example: a server answers in 10 ms but its p99 is 1 s; if a request must collect answers from 100 such servers, 63% of user requests take over one second. The 63% is just 1 − 0.99^100 = 0.634 (I computed it; it assumes servers are slow independently). Fixes from the paper include "hedged requests" (send a backup copy after a short wait and use whichever answers first). The Google SRE book adds: "a high-order percentile, such as the 99th or 99.9th, shows you a plausible worst-case value", while averaging "obscures" a long tail. Sources: The Tail at Scale, SRE book ch. 4.

Set goals on p99, not the average. In fan-out systems, the p99 of one server becomes the normal case for users.

Sources: Dean & Barroso, The Tail at Scale, CACM 2013 (63% figure confirmed via the morning paper summary); sre.google · Service Level Objectives

06Little's Law

In flight = arrival rate × time inside deep dive

Little's Law is one line: L = λ × W.

  • L: average number of requests inside the system right now (in flight).
  • λ (lambda): average arrival rate, like requests per second.
  • W: average time each request spends inside (latency).
Little's Law as a waiting room Requests arrive at 1,000 per second, stay 0.2 seconds, so on average 200 are inside the system. COME IN GO OUT Arrivalsλ = 1,000/s Inside nowL = 200 DoneW = 0.2 s each LEGEND What you solve for: L = λ × W
1,000 per second × 0.2 seconds each = 200 inside at any moment.

Interview use: "We get 1,000 RPS and each call takes 200 ms. How many threads or connections do we need?" About 200 busy at once, plus headroom.

In everyday words
A coffee shop gets 2 customers a minute and each stays 30 minutes. On average 60 people are inside, so you need about 60 seats.
Actually
John Little proved it in 1961 ("A Proof for the Queuing Formula: L = λW", Operations Research 9(3), 383–387). It holds for long-run averages in a stable (stationary) system, whatever the arrival pattern or service order. It does not hold during a spike when the queue keeps growing. So use it for sizing pools (threads, DB connections), not for predicting one bad minute. Source: Little's law.

If latency doubles at the same traffic, the number of busy connections doubles too. That is how a slow database empties a connection pool.

Source: en.wikipedia.org · Little's law, citing Little (1961), Operations Research 9(3)

Reliability

07Availability and the "nines"

Each extra nine allows ten times less downtime core interview favourite

Availability is the share of time a service works. People say it in "nines": 99.9% is "three nines".

The maths is simple. Allowed downtime = (1 − availability) × the time window.

Allowed downtime per year, in minutes

Formula: (1 − A) × 365 × 24 × 60. Each step down is ten times smaller. Hover for the exact number.

99% (two nines)
5,256
99.9% (three nines)
525.6
99.99% (four nines)
52.6
99.999% (five nines)
5.26
Show the full table
AvailabilityPer yearPer 30-day monthPer day
99%3.65 days7.2 hours14.4 min
99.9%8.76 hours43.2 min1.44 min
99.95%4.38 hours21.6 min43.2 s
99.99%52.6 min4.32 min8.64 s
99.999%5.26 min25.9 s0.87 s

Parts in a chain multiply. Two parts at 99.9% in series (both must work) give 0.999 × 0.999 = 99.8%. Two copies in parallel (either one is enough) give 1 − 0.001² = 99.9999%, but only if they fail independently.

# series: every part must be up
A_total = A1 × A2 × A3 ...
# parallel: at least one copy must be up (independent failures)
A_total = 1 − (1 − A)^n
In everyday words
Christmas lights on one wire: if any bulb fails, all go dark (series). Two separate light strings: the room stays lit unless both fail (parallel).
Actually
The Google SRE book's availability table gives exactly these numbers: 99.9% = 8.76 hours a year and 43.2 minutes a month; 99.99% = 52.6 minutes a year. I recomputed them with the formula above (30-day month) and they match. The book also says time-based availability = uptime / (uptime + downtime), and Google often uses a request-based version instead: successful requests / total requests. The "independent failures" condition is the catch: two servers in one data center share power and network, so their failures are not independent. Sources: SRE book availability table, SRE book ch. 3.

Every dependency in the request path lowers your availability. Redundancy raises it, but only across failure domains that are truly separate.

Sources: sre.google · Availability Table; sre.google · Embracing Risk; my own arithmetic (checked with Python)

08SLI, SLO and SLA

Measure, target, promise core

From SLI to SLO to SLA You measure a number (SLI), set an internal target on it (SLO), and promise customers a looser target with penalties (SLA). AIM AT SIGN AS MeasureSLI: % good TargetSLO: internal PromiseSLA: + penalty LEGEND The one engineers run on Contract with customers
The SLO sits inside the SLA, so you notice trouble before you owe money.
TermGoogle SRE book definitionExample
SLI (indicator)"a carefully defined quantitative measure of some aspect of the level of service"Share of requests that return non-5xx in under 300 ms
SLO (objective)"a target value or range of values for a service level that is measured by an SLI"That SLI ≥ 99.9% over 28 days
SLA (agreement)"an explicit or implicit contract with your users that includes consequences of meeting (or missing) the SLOs they contain"Below 99.5% in a month → service credit refund

The error budget is 100% minus the SLO. At 99.9%, you may "spend" 0.1% of requests on failures, for example on risky releases.

In everyday words
Your speedometer is the SLI. "I drive under 100 km/h" is your SLO. The legal speed limit with a fine is the SLA. You keep your own limit stricter, so you never get the fine.
Actually
The definitions in the table are quoted from chapter 4 of the Google SRE book. The examples in the right column are mine, made up to show the shape. The book's rule of thumb: if missing the target has no explicit consequence, you are talking about an SLO, not an SLA. Source: sre.google · Service Level Objectives.

In an interview, turn "it should be fast and reliable" into one SLI with one SLO, such as "p99 read latency under 200 ms, 99.9% of the time".

Source: sre.google · Chapter 4, Service Level Objectives

09Single point of failure and redundancy

Find the one box whose death kills everything core

A single point of failure (SPOF) is any part with no backup. If it stops, the whole system stops.

The fix is redundancy: run two or more copies, and switch to a healthy one when one dies. That switch is called failover.

A single database is a single point of failure Two app servers are redundant, but both depend on one database; a standby copy of the database removes the single point of failure. COPY Users Balancerx2 in real life App A App B Databaseonly one Standbythe fix LEGEND Single point of failure Spare copy, takes over
Two app servers look safe, but they both lean on one database.
LayerCommon SPOFUsual redundancy
EntryOne load balancer, one DNS providerLoad balancer pair or managed LB; multiple DNS name servers
AppOne serverN stateless copies across zones
DataOne databasePrimary + replicas with automatic failover (page 07)
LocationOne data center or zoneSpread across availability zones or regions
People / configOne bad deploy to every server at onceStaged (canary) rollouts
In everyday words
A plane has two engines, so one can fail and it still lands. But if both engines share one fuel pipe, that pipe is the real single point of failure.
Actually
Redundancy only helps if failures are independent. Azure's guidance suggests "scaling out across multiple availability zones" so that the copies do not share one zone's outage. Failover is not free: the standby must have fresh data (replication lag), and something must decide the old primary is really dead. That decision is the hard part; page 08 covers it (consensus). Source: Azure: Design to scale out.

After you draw a design, point at each box and ask "what if this dies?" Interviewers expect you to do this unprompted.

Source: learn.microsoft.com · Design to scale out ("Consider scaling for redundancy")

Estimation

10Numbers to know: powers of two and latency

The two tables behind every whiteboard estimate memorise

Powers of two and data sizes

PowerExactAboutName
2¹⁰1,0241 thousandKB (kilobyte)
2²⁰1,048,5761 millionMB
2³⁰1,073,741,8241 billionGB
2⁴⁰≈1.1 × 10¹²1 trillionTB
2⁵⁰≈1.13 × 10¹⁵1 quadrillionPB
ThingSizeNote
ASCII character1 byteUTF-8 non-English text is 2–4 bytes per character
32-bit int4 bytesmax about 2.1 billion (signed)
64-bit int / timestamp8 bytesuse for IDs at scale
UUID16 bytes128 bits (RFC 9562); 36 characters as text

Time

WindowSecondsRound to
1 day86,40010⁵
30-day month2,592,0002.5 × 10⁶
365-day year31,536,0003 × 10⁷
1 million requests per day≈11.6 per secondabout 12 QPS

Latency numbers (approximate)

How long common operations take

Bar length is on a log scale (each step is 10x), from Peter Norvig's table. Hover for the exact time.

L1 cache fetch
0.5ns
Branch mispredict
5ns
L2 cache fetch
7ns
Mutex lock/unlock
25ns
Main memory fetch
100ns
Send 2 KB, 1 Gbps
20µs
Read 1 MB from memory
250µs
Disk seek
8ms
Read 1 MB from disk
20ms
US ↔ Europe round trip
150ms
Show the full table
OperationTime (ns)Human scale
Fetch from L1 cache0.5half a nanosecond
Branch misprediction5
Fetch from L2 cache7
Mutex lock/unlock25
Fetch from main memory1000.1 µs
Send 2 KB over 1 Gbps network20,00020 µs
Read 1 MB sequentially from memory250,0000.25 ms
Disk seek (new location)8,000,0008 ms
Read 1 MB sequentially from disk20,000,00020 ms
Send packet US → Europe → US150,000,000150 ms
In everyday words
If reading from memory were a walk to the fridge, reading from a spinning disk would be a trip to the shop, and a round trip to Europe would be a long holiday.
Actually
These are from Peter Norvig's "Teach Yourself Programming in Ten Years" table, "Approximate timing for various operations on a typical PC" (Jeff Dean popularised a similar list). They are old and approximate. Modern SSDs and networks are much faster than the "disk" rows, but the ratios still teach the point: memory ≫ SSD ≫ spinning disk, and crossing an ocean costs about 150 ms no matter how fast your code is. I did not verify modern SSD numbers here (not proven). Source: norvig.com/21-days.html.

Memory is about 80x faster than disk for a 1 MB read in this table. That ratio is why caches exist (page 04).

Sources: Peter Norvig · Teach Yourself Programming in Ten Years; RFC 9562 (UUIDs, 128 bits); powers of two and time are arithmetic

11Worked estimate: a photo-sharing app

From users to QPS, storage and bandwidth in five lines interview favourite

Write your assumptions first, out loud. The interviewer can then correct them. All numbers below are my assumptions, not real data from any app.

From daily users to peak QPS Daily users times actions per user gives requests per day; divide by 86,400 for average QPS; multiply by a peak factor for peak QPS. Daily users10M DAU Per day× actions Average QPS÷ 86,400 Peak QPS× 2 to 3 LEGEND The number you size servers for Your assumption
Always size for the peak, not the average.

Step 1: assumptions

AssumptionValueWhy this guess
Daily active users (DAU)10 millionMid-size app
Photos uploaded per user per day2Most users only view
Average stored photo size2 MBCompressed phone photo
Photos viewed per user per day50Scrolling a feed
Size sent per view200 KBFeed-sized copy, not the original
Copies kept of each photo3Replication for durability
Peak ÷ average traffic3Evening rush; a common rule of thumb

Step 2: the maths

# Write QPS (uploads)
10M users × 2 uploads        = 20M uploads/day
20M ÷ 86,400 s               ≈ 231 QPS average   (shortcut: 20M ÷ 10^5 = 200)
231 × 3                      ≈ 700 QPS at peak

# Read QPS (views)
10M users × 50 views         = 500M views/day
500M ÷ 86,400 s              ≈ 5,800 QPS average
5,800 × 3                    ≈ 17,400 QPS at peak

# Storage
20M photos × 2 MB            = 40 TB per day
40 TB × 365                  = 14.6 PB per year
14.6 PB × 3 copies           ≈ 44 PB per year of raw disk

# Bandwidth
In:  40 TB/day ÷ 86,400      ≈ 463 MB/s  ≈ 3.7 Gbps
Out: 500M × 200 KB = 100 TB/day ÷ 86,400 ≈ 1.16 GB/s ≈ 9.3 Gbps

Step 3: what the numbers tell you

Average reads vs writes per second

From the maths above. Reads are 25 times writes.

Reads (views)
5,787
Writes (uploads)
231
Show the full table
ResultAveragePeak (×3)Design impact
Read QPS5,78717,361Read-heavy: CDN + cache in front of storage
Write QPS231694Small; one metadata DB primary can take it
New storage per year43.8 PB—Object storage (like S3), not a database
Egress9.3 Gbps28 GbpsServe images from a CDN
In everyday words
Like planning a wedding: guests × plates each = food to buy. You do not need the exact guest count, just the right size of number.
Actually
Every result above is only my arithmetic on my stated guesses (checked with Python). The goal in an interview is the order of magnitude (hundreds vs thousands vs millions), because that decides the design: 231 writes per second fits one database; 44 PB a year does not. Say "about" and round boldly. Interviewers care that you state assumptions and use the numbers to make choices. This rubric is common practice, not proven from an official source.

The estimate is only useful if you then say what it changes: "reads are 25x writes, so I put a CDN and cache in front".

Source: arithmetic on stated assumptions; 86,400 s/day is exact.

12Read-heavy vs write-heavy systems

The read-to-write ratio picks your tools core

Most apps read far more than they write. A news feed is read many times per post. Some systems are the other way: logging, metrics, chat messages, IoT sensors.

ShapeExamplesTools that helpTrade-off
Read-heavySocial feed, product catalog, URL shortenerCache (page 04), CDN, read replicas (page 07), denormalised dataStale reads; cache invalidation is hard
Write-heavyLogs, metrics, clicks, chat, sensor dataAppend-only storage (LSM trees, page 06), queues to absorb bursts (page 09), batching, shardingReads get slower or need extra work
Both heavyRide-hailing locations, stock tradingShard by key, keep hot data in memoryHighest cost and complexity
In everyday words
A library (read-heavy) makes many copies of popular books. A post office (write-heavy) needs many sorting desks to take letters in fast.
Actually
A cache or replica only helps reads; every write still goes to the primary and must also update or invalidate the copies. So adding read replicas to a write-heavy system adds work instead of removing it. Write-heavy systems scale by splitting writes across machines (sharding) or by making each write cheap (append to a log, batch). Page 06 (LSM trees vs B-trees) and page 07 (sharding) show the mechanism. This section is a summary of later pages; proof lives there.

Say the ratio out loud ("about 25:1 reads to writes") and let it drive your first design choice.

Source: summary of this course's pages 04, 06, 07 and 09.

Practice

—When to use what

Situation → pick → why decision table

SituationPickWhy
Early product, one server is at 80% CPUScale up firstNo code change; buys time cheaply
Web/API tier must survive a server crashScale out, 2+ stateless copies across zonesRemoves the SPOF and adds capacity
Servers keep login sessions in memoryMove sessions to Redis or signed tokensLets any server answer; no sticky sessions
Writing a speed goalp99 (and p50) latency SLOAverages hide the tail users feel
Request calls many backends in parallelHedged requests, timeouts, fewer fan-out callsTail latency multiplies with fan-out
Sizing a thread or DB connection poolLittle's Law: λ × W, plus headroomGives the in-flight count directly
Choosing an availability targetThe lowest nines users truly needEach nine costs about 10x less downtime budget and more money
Reads ≫ writesCache, CDN, read replicasServe repeats without touching the primary
Writes ≫ readsQueue + batch + shard, append-only storageSpread and cheapen each write

—Common mistakes

Traps interviewers see every day traps

Trap
Using the average latency
Averages hide the slow 1%. Quote p50 and p99.
Trap
"Just add servers"
If the database is the bottleneck, more web servers do nothing.
Trap
Forgetting the peak
Average QPS sizes nothing. Multiply by a peak factor and say which.
Trap
False precision
"5,787.04 QPS" wastes time. Say "about 6,000".
Trap
Hidden SPOF
Two app servers, one database, one load balancer. Still one failure away from down.
Trap
Assuming copies fail separately
Same zone, same deploy, same bug: they fail together.
Trap
Bits vs bytes
Network is in bits per second. 1 GB/s = 8 Gbps.
Trap
Mixing SLO and SLA
The SLA has a penalty. The SLO is your own stricter goal.

—Interview questions

18 questions, easy to hard, with model answers practice

What is the difference between vertical and horizontal scaling? easy
Show answer

Vertical scaling makes one machine bigger (more CPU, RAM). Horizontal scaling adds more machines behind a load balancer.

Vertical is simple and needs no code change, but it has a hard ceiling and the machine is still a single point of failure. Horizontal has a much higher ceiling and survives a machine dying, but the app must be stateless and you now need load balancing, health checks and deployment across many nodes.

I usually scale the stateless web tier out from day one (2+ instances for redundancy) and scale the database up first, because databases are harder to split. Follow-up: "What do you do when the database maxes out?" → read replicas, caching, then sharding.

What makes a service stateless, and why do we want it? easy
Show answer

A stateless service keeps no per-user data in its own memory or disk between requests. Session data, carts and uploads live in a shared store (Redis, a database, S3) or in a signed token the client sends.

Why: any instance can serve any request. So the load balancer can use simple round robin, you can add or remove instances freely (autoscaling), and a crash loses nothing. Twelve-Factor calls sticky sessions "a violation".

Trade-off: every request now reads state over the network (a network round trip, instead of a ~100 ns local memory read), and the shared store must itself be made highly available.

Latency vs throughput: explain, with an example where improving one hurts the other. easy
Show answer

Latency is the time for one request; throughput is how many requests complete per second.

Batching is the classic trade: if a service waits to collect 100 writes and flushes them together, throughput rises (one disk sync for 100 writes) but each write waits for the batch, so latency rises. Kafka producers do exactly this with a small linger time.

The other direction: running a server at 95% CPU maximises throughput per machine but queueing makes latency spike. That is why we leave headroom, often targeting around 60–70% utilisation (a rule of thumb, not a law).

Why use p99 instead of the average for latency? easy
Show answer

Because the average hides the slow requests that users actually complain about. If 99 requests take 10 ms and one takes 2 s, the average is about 30 ms, which looks great, but 1 in 100 users waits two seconds.

p99 says "99% of requests were this fast or faster". The Google SRE book recommends high percentiles because they show "a plausible worst-case value".

Also, heavy users make many requests per page, so they hit the tail often. I would set SLOs on p50 and p99, and alert on p99.

How much downtime does 99.9% allow per month? And 99.99% per year? easy
Show answer

99.9% allows about 43 minutes per 30-day month (0.001 × 30 × 24 × 60 = 43.2). 99.99% allows about 52.6 minutes per year (0.0001 × 525,600).

The quick rule: each extra nine cuts the budget by 10x. Three nines ≈ 8.8 hours a year; four ≈ 53 minutes; five ≈ 5 minutes.

Why it matters: at five nines, a human cannot even get paged and log in before the budget is gone, so recovery must be automatic. These numbers match the Google SRE book's availability table.

Define SLI, SLO and SLA and give one example of each. easy
Show answer

SLI is the measurement: for example, the fraction of HTTP requests that succeed in under 300 ms. SLO is the internal target on that SLI: 99.9% over a rolling 28 days. SLA is the external contract with consequences: below 99.5% in a month, customers get a 10% credit.

The SLO is stricter than the SLA so the team reacts before money is owed. 100% minus the SLO is the error budget; when it is spent, teams slow down risky launches.

Follow-up: "Why not target 100%?" → it is impossible to reach and the cost explodes; users cannot tell 99.999% from 100% when their own Wi-Fi is less reliable.

What is a single point of failure? Find the SPOFs in "LB → 3 app servers → 1 MySQL". easy
Show answer

A SPOF is any component with no redundant copy, so its failure stops the whole system.

Here: the single load balancer and the single MySQL instance. The three app servers are fine if they are stateless and spread over zones. Less obvious ones: one DNS provider, one availability zone, one config or deploy pipeline that pushes a bad change everywhere.

Fixes: managed or paired load balancers, MySQL primary + replica with automatic failover (accepting a few seconds of failover time and possible replication lag), multi-AZ placement, and staged rollouts.

State Little's Law and use it to size a database connection pool. medium
Show answer

L = λ × W: average items in the system equals arrival rate times average time in the system. It holds for long-run averages in a stable system.

Example: the service sends 2,000 queries per second to the database and each holds a connection for 5 ms. L = 2,000 × 0.005 = 10 connections busy on average. I would give the pool maybe 2–3x that for bursts, so 20–30.

The scary part: if a slow query makes W jump to 500 ms, L jumps to 1,000. The pool runs out and requests queue. That is why we set query timeouts and watch pool wait time.

A request fans out to 100 backends. Each backend's p99 is 1 s, its median 10 ms. What is the user's experience? How do you fix it? medium
Show answer

The user waits for the slowest of 100. The chance all 100 are fast is 0.99^100 ≈ 37%, so about 63% of user requests take over a second. This is the "Tail at Scale" example from Dean and Barroso.

Fixes: hedged requests (send a second copy after, say, the p95 time and take whichever finishes first; costs a few percent extra load), tied requests, timeouts with partial results ("good enough" search results), reducing fan-out with better partitioning, and fixing the causes of slow outliers (GC pauses, noisy neighbours, background jobs).

Follow-up: "What does hedging cost?" → extra load, roughly the share of requests that hit the hedge threshold.

Two services in series, each 99.9% available. What is the total? What if you run two copies of each in parallel? medium
Show answer

In series both must work: 0.999 × 0.999 ≈ 99.8%. So 10 dependencies at 99.9% each give only about 99.0%.

Two independent copies of one service in parallel: 1 − 0.001² = 99.9999%. Then the chain of two such pairs is about 99.9998%.

The catch is "independent". Copies in the same zone, on the same version, sharing the same database, fail together. Real gains come from spreading across zones, staged deploys and removing shared dependencies. This is why microservice chains often have worse availability than a monolith unless calls are made optional or async.

Estimate QPS and storage for a URL shortener with 100M new URLs per month. medium
Show answer

Writes: 100M ÷ (30 × 86,400 ≈ 2.6M s) ≈ 40 writes/s; peak ×3 ≈ 120. Assume reads are 100:1 → about 4,000 reads/s average, 12,000 peak.

Storage: each record (short code 7 B, long URL ~100 B, timestamps, user ID) ≈ 500 B with overhead. 100M × 500 B = 50 GB a month, about 600 GB a year, 3 TB over five years.

So what: writes are tiny, reads are cache-friendly (hot links), and the data fits on one machine for years. I would use a cache in front of a key-value store and not shard on day one. All inputs are assumptions I would confirm with the interviewer.

Your service has 1 million DAU, each making 20 requests a day. How many servers do you need? medium
Show answer

Requests per day = 20M. Average QPS = 20M ÷ 86,400 ≈ 230; peak at 3x ≈ 700.

Servers depend on cost per request, which I would ask about or measure. If one instance handles about 500 RPS for this workload at safe CPU (an assumption to load-test), then 700 ÷ 500 → 2 servers, and I would run 3 for redundancy across zones (N+1).

The point is to show the chain: users → requests/day → average → peak → per-server capacity → count + redundancy. The per-server capacity must come from a load test, not a guess.

What breaks when you move a stateful web app (in-memory sessions) behind a round-robin load balancer? medium
Show answer

Users get logged out or lose carts at random, because request 2 lands on a server that does not have the session from request 1. In-memory caches also diverge between servers.

Quick fix: sticky sessions (LB pins a user to one server by cookie). It works, but load becomes uneven, a server crash still loses those sessions, and draining servers for deploys is slow.

Proper fix: move session state to Redis/Memcached with a TTL, or use signed tokens (like JWT) so the server needs no session store. Then any server can answer and autoscaling just works.

Bandwidth check: 1 million users each stream 2 Mbps video at peak. How much egress? medium
Show answer

1,000,000 × 2 Mbps = 2,000,000 Mbps = 2 Tbps (terabits per second). In bytes that is 250 GB/s.

No single data center link or server fleet serves that cheaply. So the design must use a CDN with edge caches close to viewers, and pre-encoded segments at several bitrates so clients can step down on bad networks.

Common slip: mixing bits and bytes. Network speeds are quoted in bits; storage in bytes. Divide bits by 8.

Why does latency shoot up when a server nears 100% utilisation, even if throughput looks fine? hard
Show answer

Because requests start waiting in a queue. Near full use, any small burst arrives faster than the server can drain it, and the queue grows. In simple queueing models, waiting time grows roughly like 1 ÷ (1 − utilisation): at 50% it is modest; at 90% it is about 5x worse than at 50%; at 99% it explodes.

By Little's Law, more time waiting means more requests in flight, which uses up threads and connections, which causes timeouts and retries, which adds load: a feedback loop.

So we keep headroom, autoscale on queue length or latency (not only CPU), and shed load (return 429 or 503) instead of letting queues grow without limit.

Your SLO is 99.9% monthly and you have used 80% of the error budget by day 10. What do you do? hard
Show answer

The monthly budget at 99.9% is about 43 minutes of full downtime (or 0.1% of requests). Using 80% by day 10 means we are burning about 2.4x faster than sustainable.

Actions, per the SRE error-budget idea: freeze or slow risky launches, put engineers on reliability work, find the top causes of bad events, and add burn-rate alerts (alert when the budget would run out in hours or days, not when it is already gone).

Also check that the SLI is right: if users are happy, maybe the SLO is too strict. The budget is a tool to balance speed and reliability, not a punishment.

Design-style: estimate the infrastructure for a chat app with 50M DAU, 40 messages each per day, kept forever. hard
Show answer

Messages: 50M × 40 = 2B a day ≈ 23,000 writes/s average, about 70,000 peak. That is write-heavy and too much for one SQL primary, so I would shard by conversation ID and use a store good at appends (for example Cassandra-style wide rows).

Storage: about 100 B of text + 100 B metadata ≈ 200 B per message → 400 GB a day → 146 TB a year, ×3 replicas ≈ 440 TB a year. Media goes to object storage instead.

Connections: 50M daily users, maybe 10M online at once, each holding a WebSocket. At an assumed 50,000–100,000 connections per gateway server, that is 100–200 gateway servers. All inputs are assumptions to confirm.

How would you take a single-server app to 100x traffic? Walk through the order of changes. hard
Show answer

1) Measure first: find the actual bottleneck (CPU, DB queries, network). 2) Separate the database onto its own machine and scale it up. 3) Make the app stateless (sessions to Redis) and run several copies behind a load balancer across zones. 4) Add a cache for hot reads and a CDN for static files; this often removes most DB reads. 5) Add read replicas. 6) Move slow work (email, image resize) to a queue and workers. 7) Only then shard the database, because sharding is costly to undo.

Each step removes the current bottleneck and a SPOF. I would set p99 and availability SLOs first so I know when a step is "done".

—Cheat sheet

The numbers to memorise memorise

FactValueSource
Seconds per day86,400 ≈ 10⁵arithmetic
1M requests/day≈ 12 QPSarithmetic
2¹⁰, 2²⁰, 2³⁰, 2⁴⁰≈ thousand, million, billion, trillion (KB, MB, GB, TB)arithmetic
99.9% downtime8.76 h/year, 43.2 min/monthSRE book
99.99% downtime52.6 min/year, 4.32 min/monthSRE book
99.999% downtime5.26 min/yearSRE book
Series availabilitymultiply: A1 × A2probability
Parallel availability1 − (1 − A)ⁿ, if independentprobability
Little's LawL = λ × WLittle 1961
Fan-out tail1 − 0.99¹⁰⁰ ≈ 63%Tail at Scale
Main memory fetch≈ 100 nsNorvig
1 MB from memory vs disk250 µs vs 20 msNorvig
US ↔ Europe round trip≈ 150 msNorvig
Bits vs bytes1 GB/s = 8 Gbpsarithmetic

—Sources

All checked 2026-10-25 sources

WhatWhere
Availability table (nines)sre.google/sre-book/availability-table
Time-based vs request-based availabilitysre.google/sre-book/embracing-risk
SLI / SLO / SLA definitions, percentilessre.google/sre-book/service-level-objectives
Tail latency and fan-out (63%)Dean & Barroso, The Tail at Scale, CACM 2013; summary at blog.acolyer.org
Little's LawWikipedia, citing Little (1961) Operations Research 9(3):383–387
Scale out, stickiness, bottlenecks, zonesAzure Architecture Center · Design to scale out
Stateless processes, sticky sessions12factor.net/processes
Latency numbers (approximate)Peter Norvig · Teach Yourself Programming in Ten Years
UUID sizeRFC 9562
Photo-app and other estimatesMy arithmetic on stated assumptions (not data from any real app)