🧮 System Design back-of-the-envelope
🧮 Part I · Foundations · chapter 2 / 24

Get the number
in your head

Good system design starts with a rough number you can work out on a napkin in thirty seconds. This chapter teaches you to land on the right power of ten — for latency, traffic, storage, and uptime — without ever opening a spreadsheet.

In an interview — and on a real design doc — nobody wants four significant figures. They want to know whether you need one server or a thousand, gigabytes or petabytes, a cache or a whole new data tier. That answer is an order of magnitude, and you can reach it in your head.

A back-of-the-envelope estimate is a quick calculation that gets you to the right power of ten using round numbers and stated assumptions. It is deliberately sloppy in the last digit and deliberately careful about the exponent. "About 50,000 requests per second, call it 100k at peak" is a useful sentence. "47,318.6 QPS" is a false promise.

This chapter hands you the small kit you need to do this fast: the data-size units (powers of two), the latency numbers every programmer should know, and three repeatable recipes — for traffic (QPS), for storage and bandwidth, and for availability (the nines). Round aggressively, say your assumptions out loud, and sanity-check the magnitude at the end.

1Why estimate at all

Imagine an interviewer says: "Design a photo-sharing service for 100 million daily users." Before you draw a single box you have to know roughly how much traffic, data, and money you're dealing with — because the architecture for 10 requests per second looks nothing like the architecture for 10 million. Estimation is how you pick the right shape before you commit to it.

The point is never precision. You won't know the exact payload size, the exact read/write ratio, or next year's growth — and you don't need to. What you need is the order of magnitude: the power of ten that tells you whether a single Postgres box is fine, or whether you're staring down sharding, a CDN, and a queue from day one.

  • It picks the architecture. 1 GB fits in RAM; 1 PB does not. 100 QPS is one machine; 1,000,000 QPS is a fleet. The exponent decides the design.
  • It catches nonsense early. If your math says you need 40 terabytes of RAM for a chat app, you made a wrong assumption — and you'd rather find that in thirty seconds than after a sprint.
  • It shows how you think. Interviewers grade the reasoning: which numbers you reach for, how you round, whether you state assumptions. The final figure barely matters.

So the goal is a number that's right to within a factor of about ten, produced quickly, with every assumption visible. Get the power of ten right and the design follows. Chase the spreadsheet and you've missed the question.

💡
A good estimate is round, fast, and out loud. Say "assume 2 KB per record, assume 10% of users active per day, round a day to 100k seconds" — then do the arithmetic. Stated assumptions are what make a rough number trustworthy.

2Powers of two → data units

Storage and memory are measured in powers of two, but for estimation you only need to remember that each step up — kilo, mega, giga, tera, peta — multiplies by about a thousand (really 1,024, close enough). So the whole job of "how much storage?" becomes: count the bytes per thing, count the things, multiply, and slide up the ladder counting thousands.

Here is the handy table. The left column is the exact power of two; the right is the round number you actually use in your head.

PowerApprox. valueUnitFeels like
2¹⁰~1 thousand1 KB (kilobyte)a short paragraph of text
2²⁰~1 million1 MB (megabyte)a small photo / a minute of MP3
2³⁰~1 billion1 GB (gigabyte)a movie; fits in RAM
2⁴⁰~1 trillion1 TB (terabyte)one big disk
2⁵⁰~1 quadrillion1 PB (petabyte)a fleet of disks; "big data" territory

That's the entire trick for converting "X million users × Y bytes" into storage in seconds. Suppose 1 million users, each storing a 2 KB profile:

  • 1,000,000 × 2 KB = 2,000,000 KB
  • Slide up one rung (÷ 1,000): = 2,000 MB
  • Slide up again: ≈ 2 GB. Done — fits comfortably on one machine.

Want bytes-per-character intuition for sizing records? An ASCII character is 1 byte; a typical UTF-8 character is 1–4 bytes; a 64-bit integer or timestamp is 8 bytes; a UUID is 16 bytes. Add up a row's fields, round generously for overhead, and you have your "Y bytes."

λ
Every step on the ladder is the same multiply-by-a-thousand, applied again. Converting 1.2 trillion bytes to a friendly unit is just folding ÷1000 over the number until it's small: 1.2e12 → 1.2e9 GB? no → 1,200 GB → 1.2 TB. Count the rungs, not the zeros.

3Latency numbers every programmer should know

The single most clarifying set of numbers in our field is the cost of moving data at each level of the machine. Reading from a CPU cache is almost free; reaching across an ocean is agonizing. Memorize the rough hierarchy and you can guess where a system's time actually goes before you profile anything.

OperationReal timeLayer
L1 cache reference~1 nson-chip
L2 cache reference~4 nson-chip
Main memory (RAM) reference~100 nsmemory — fast
SSD random read~16 µsdisk — slow
Datacenter round trip~0.5 msnetwork — slower
Rotating disk seek~few msdisk — slow
California ↔ Netherlands round trip~150 mscross-continent — glacial

The shape to internalize: memory is fast, disk is slow, the network is slower, and crossing a continent is glacial. Each tier is roughly 100–1000× the one above it. RAM is about 100× slower than L1; an SSD read is ~150× slower than RAM; a transatlantic hop is ~300× slower than a datacenter round trip and around 100 million times slower than an L1 reference.

That last gap is hard to feel, so rescale it to human time. Pretend an L1 cache hit takes 1 second. Then everything else inflates by the same factor (~10⁹):

  • L1 cache — 1 second (a heartbeat)
  • RAM — ~1.5 minutes (brewing coffee)
  • SSD read — ~4.5 hours (a workday)
  • Datacenter round trip — ~5.5 days (a holiday)
  • Transatlantic round trip — ~4.7 years (a degree)

If a cache hit is one heartbeat, a transatlantic hop is most of a university degree. That is why we cache, why we put a CDN near the user, and why "just call the other datacenter" is never free.

Interactive · human-scaled latency ladder Hover a bar · toggle to rescale L1 = 1 second
log scale · ~1 ns → ~150 ms
🌍
Bars on a log scale: each tick is 10× the last, otherwise L1 would be one pixel and the ocean would run off the page. The toggle keeps the bars identical but re-labels them in human terms — the gap you see is the gap that matters.

4QPS estimation

The first number any traffic question wants is QPS — queries (or requests) per second. You build it up from how many people use the product and how often, then adjust for the fact that traffic clumps into a busy part of the day.

Start with DAU (daily active users) — how many distinct people use the app on a given day. Decide how many requests each makes per day. Multiply to get requests per day, then divide by the number of seconds in a day to get the average QPS.

The one fact you must keep loaded: a day has 24 × 60 × 60 = 86,400 seconds. For mental math, round it to 100,000 (10⁵). You'll be ~15% low on the denominator, which makes your QPS ~15% high — a safe, conservative direction, and well within "order of magnitude." So:

  • requests/day = DAU × requests per user per day
  • average QPS = requests/day ÷ ~100,000
  • peak QPS = average QPS × a peak multiplier of about 2–5× (traffic isn't flat; it bunches at busy hours)

Worked example. Say 10 million DAU, each making 20 requests a day:

  • 10,000,000 × 20 = 200,000,000 requests/day
  • 200,000,000 ÷ 100,000 = 2,000 average QPS
  • Apply a 3× peak: 2,000 × 3 = 6,000 peak QPS — design for this number.

One more split that changes the design: reads vs writes. Most consumer apps are heavily read-skewed (people scroll far more than they post), often 10:1 or 100:1. So of that 6,000 peak QPS you might have ~5,400 reads and ~600 writes — which tells you to scale reads with replicas and a cache, and to size the write path more modestly.

Interactive · estimator scratchpad Slide the inputs · read the math step by step
10 M
20
2 KB
3 yr
average QPS
peak QPS
storage (w/ replicas)
peak bandwidth

5Storage & bandwidth estimation

Storage asks "how many bytes will we be sitting on?" and bandwidth asks "how many bytes per second are flowing?" They're different questions with the same ingredients: a per-record size and a volume.

Storage = size × volume × retention × replication

Take the bytes in one record, multiply by how many records you create over the period you keep them, then multiply by how many copies you keep for safety:

  • per-record size — add up the fields, round up for overhead (indexes, padding).
  • volume — new records per day × days. (Writes per day, often.)
  • retention — how long you keep the data. "Forever" means multiply by years.
  • replication — most systems keep ~3 copies, so multiply by 3.

Example: 600 writes/sec of 2 KB each, kept for 3 years, replicated 3×.

  • per day: 600 × 86,400 ≈ 5.2e7 writes/day × 2 KB ≈ 100 GB/day
  • over 3 years: 100 GB × 365 × 3 ≈ 110 TB
  • with 3× replication: ≈ 330 TB — now you know you need a real storage tier, not one disk.

Bandwidth = QPS × payload

Bandwidth is the simplest of all: requests per second times bytes per request. At 6,000 peak QPS of 2 KB responses: 6,000 × 2 KB = 12 MB/s ≈ 96 Mbps. Modest. Now make the payload a 2 MB photo and it's 6,000 × 2 MB = 12 GB/s — a completely different (and expensive) system.

Which direction dominates? Almost always egress — bytes flowing out to users. Reads outnumber writes, responses are usually bigger than requests, and cloud providers bill outbound traffic heavily while inbound is often free. So size the read/egress path first; it's where both the capacity and the bill live.

⚠️
Don't forget the multipliers. The number that surprises people is never the raw record size — it's retention × replication. A tidy 100 GB/day becomes hundreds of terabytes once you keep it for years and copy it three times. Always carry both factors through.

6Availability & the nines

Availability is the fraction of time a system is up and serving. We quote it in "nines" — and the difference between one more nine is the difference between hours and minutes of yearly downtime. Memorize this table; it comes up constantly.

AvailabilityNameDowntime / yearDowntime / day
99%"two nines"~3.65 days~14.4 min
99.9%"three nines"~8.8 hours~1.4 min
99.99%"four nines"~52.6 min~8.6 sec
99.999%"five nines"~5.3 min~0.86 sec

The trap nobody expects: availabilities multiply across components you depend on. If a request must pass through three services in series, and each is up 99.9% of the time, the chain isn't 99.9% — it's 0.999 × 0.999 × 0.999 ≈ 0.997 = 99.7%. The whole is always worse than its weakest dependency, because they all have to be up at once. Ten such services in a row drop you to ~99% — back to days of downtime a year.

Two ways out. Reduce the number of things in the critical path, or add redundancy: run two of a component so the request succeeds if either is up. Then the failures multiply instead — two 99.9% replicas fail together only 0.1% × 0.1% = 0.0001% of the time, giving 99.9999%. Redundancy in parallel adds nines; dependencies in series subtract them.

SLA vs SLO vs SLI

  • SLI — Indicator. The thing you actually measure: "% of requests served in under 200 ms," "% of minutes the API was up." The raw number.
  • SLO — Objective. The internal target you hold yourselves to: "99.95% of requests succeed each month." A goal, no money attached.
  • SLA — Agreement. The contractual promise to customers, with penalties (refunds, credits) if you miss it. Always looser than your SLO, so you have margin before the lawyers get involved.

Mnemonic: you measure the SLI, you aim for the SLO, and you promise the SLA. SLI ⊆ SLO ⊆ SLA in strictness.

Interactive · nines calculator Pick a target · chain components · flip redundancy
99.9%
3
combined availability
downtime / year
downtime / month
downtime / day

7Rounding & sanity discipline

The skill that separates a clean estimate from a stuck whiteboard isn't arithmetic — it's knowing what to throw away. Three habits do almost all the work.

  • Round aggressively, and round early. 86,400 → 100,000. 365 → 400 (or just "a year"). 1,024 → 1,000. Pick round numbers so you can multiply in your head, and prefer rounding in the conservative (over-provisioning) direction so your answer errs toward "build it a bit bigger."
  • State every assumption out loud. "Assume 2 KB per record. Assume 10% of users active daily. Assume a 3× peak." Each one is a knob the interviewer can turn — and naming them is what makes the final number defensible rather than magic.
  • Sanity-check the magnitude at the end. Does the answer pass the smell test? 40 TB of RAM for a chat app — no. 6,000 QPS for a mid-size social feed — sounds right. If a number feels absurd, one of your assumptions is off by a factor of ten; find it before you trust the design.

Keep the kit small and the assumptions visible, and you'll land on the right power of ten faster than anyone reaching for a calculator. That's the whole game.

  1. 1Units ladder — KB → MB → GB → TB → PB, each ~×1000. Count rungs, not zeros.
  2. 2Latency hierarchy — memory ns, disk µs, network sub-ms, ocean ~150 ms. Cache and place data near the user.
  3. 3QPS — DAU × req/user ÷ 100k = avg; ×(2–5) = peak; split reads from writes.
  4. 4Storage — size × volume × retention × replication. The multipliers bite.
  5. 5Bandwidth — QPS × payload; egress dominates the capacity and the bill.
  6. 6Nines — series multiplies down, redundancy multiplies failures down. Know the downtime table.
  7. 7Discipline — round hard, assume out loud, sanity-check the exponent.

8The estimate, as a pure function

Every recipe in this chapter is the same: take a handful of assumptions in, return the numbers out, with no hidden state. That is exactly a pure function — which is why the estimator scratchpad above can recompute instantly on every slider move. Here it is in code; the cache hit and the ocean hop don't appear, just the arithmetic. Flip between the two languages — the shape is identical.

λ
Assumptions in, estimate out, nothing remembered between calls. Because it's pure you can test it, slide it live, or fold it over a whole catalog of services — and a back-of-the-envelope estimate is just this function evaluated in your head.