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.
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.
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.
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.
| Power | Approx. value | Unit | Feels like |
|---|---|---|---|
| 2¹⁰ | ~1 thousand | 1 KB (kilobyte) | a short paragraph of text |
| 2²⁰ | ~1 million | 1 MB (megabyte) | a small photo / a minute of MP3 |
| 2³⁰ | ~1 billion | 1 GB (gigabyte) | a movie; fits in RAM |
| 2⁴⁰ | ~1 trillion | 1 TB (terabyte) | one big disk |
| 2⁵⁰ | ~1 quadrillion | 1 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:
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."
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.
| Operation | Real time | Layer |
|---|---|---|
| L1 cache reference | ~1 ns | on-chip |
| L2 cache reference | ~4 ns | on-chip |
| Main memory (RAM) reference | ~100 ns | memory — fast |
| SSD random read | ~16 µs | disk — slow |
| Datacenter round trip | ~0.5 ms | network — slower |
| Rotating disk seek | ~few ms | disk — slow |
| California ↔ Netherlands round trip | ~150 ms | cross-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⁹):
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.
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:
Worked example. Say 10 million DAU, each making 20 requests a day:
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.
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.
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:
Example: 600 writes/sec of 2 KB each, kept for 3 years, replicated 3×.
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.
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.
| Availability | Name | Downtime / year | Downtime / 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.
Mnemonic: you measure the SLI, you aim for the SLO, and you promise the SLA. SLI ⊆ SLO ⊆ SLA in strictness.
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.
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.
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.