Capacity Estimation — Back-of-Envelope Math
The 3-5 minute phase that turns “design a system” into “design a system at this scale.” You’re not aiming for precision — you’re deriving whether you need one server or a thousand, one database or a sharded fleet.
The numbers to memorize
Round everything. These are the anchors:
| Quantity | Round to |
|---|---|
| Seconds in a day | ~100,000 (actually 86,400) |
| Seconds in a month | ~2.5 million |
| 1 KB | 10³ bytes |
| 1 MB | 10⁶ |
| 1 GB | 10⁹ |
| 1 TB | 10¹² |
| Char / small field | ~1-10 bytes |
| A typical JSON record | ~1 KB |
| A small image | ~100 KB-1 MB |
| A row in Postgres | ~hundreds of bytes-few KB |
The four estimates
1. QPS (queries per second)
QPS = DAU × actions_per_user_per_day ÷ seconds_per_day
peak_QPS = QPS × peak_factor (peak_factor ≈ 2-3)
Example — 10M DAU, each does 10 reads + 1 write per day:
reads: 10M × 10 ÷ 100k = 1,000 QPS average → ~2-3k peak
writes: 10M × 1 ÷ 100k = 100 QPS average → ~200-300 peak
That’s a single beefy database for writes, a cache + a few read replicas for reads. Not a sharding problem yet — and saying that is the insight.
2. Storage
storage_per_day = items_per_day × bytes_per_item
total_storage = storage_per_day × retention_days
Example — 1M new posts/day, ~1 KB each, kept forever:
per day: 1M × 1 KB = 1 GB/day
per year: 1 GB × 365 ≈ 365 GB/year
5 years: ~2 TB
2 TB fits on one machine. If it were 1 GB per second, you’d be reasoning about a partitioned store. The number tells you which conversation to have.
3. Bandwidth
bandwidth = QPS × payload_size
Example — 3k read QPS, 5 KB response each:
3,000 × 5 KB = 15 MB/s outbound
Modest. If responses were 5 MB (video), it’d be 15 GB/s and the design is now about CDN and egress cost.
4. Memory (for caching)
cache_size = items_to_cache × bytes_per_item
Example — cache the hottest 20% of 100M items, 1 KB each:
20M × 1 KB = 20 GB
20 GB fits in one large Redis node. 2 TB doesn’t — that’s a Redis cluster. Again: the number picks the architecture.
The read:write ratio
Often the single most design-shaping number. Consumer apps are typically 10:1 to 100:1 read:write.
- Very read-heavy → aggressive caching, read replicas, denormalization, fan-out-on-write.
- Write-heavy → queue to absorb spikes, partition the write path, fan-out-on-read.
State it explicitly: “this is ~50:1 read:write, so I’ll optimize the read path with a cache and replicas, and the write path can be simple.”
Worked example — a URL shortener
Requirements: 100M new URLs/month, 10:1 read:write (people click more than they create).
Writes:
100M / month ÷ 2.5M sec = 40 writes/sec average → ~100 peak
Reads:
40 × 10 = 400 reads/sec average → ~1,000 peak
Storage:
100M URLs/month × 12 months × 5 years = 6B URLs
per URL: short_code(7B) + long_url(~100B) + metadata(~100B) ≈ 500 B
6B × 500 B = 3 TB over 5 years
Bandwidth:
reads return a 302 (tiny) → negligible
writes ~200 B each × 100/s → trivial
Cache:
hot 20% of URLs: 1.2B × 500 B = 600 GB → a Redis cluster, or cache only the truly hot tail
Conclusion you’d state: “Write QPS is low — a single primary handles it. Reads are 1k peak — a cache absorbs most. Storage is 3 TB over 5 years — fits on one machine with room, but I’d plan partitioning by short_code prefix for headroom. Nothing here forces exotic infrastructure.”
That paragraph — derived from arithmetic — is worth more than any diagram.
Estimation discipline
- Round hard, round early. 86,400 → 100,000. 365 → 400 if it helps. Note the direction.
- One significant figure is fine. You’re choosing between “1 server” and “100 servers,” not “37 vs 41.”
- State assumptions. “Assume 10M DAU and 10 reads each” — the interviewer corrects you if it matters, and now your math is anchored.
- Do it out loud. The arithmetic is the artifact being scored, not the final number.
- Sanity-check the result. “3 TB over 5 years” — does that feel right for a URL shortener? Yes. “3 PB”? You made an arithmetic error; find it.
When the number changes the design
| If the estimate says… | The design becomes… |
|---|---|
| < ~5k write QPS, < few TB | single primary DB, maybe read replicas — don’t shard |
| 10k+ write QPS or 10+ TB | partitioned/sharded store, or DynamoDB |
| read:write > 20:1 | cache + replicas + denormalization is the main effort |
| bandwidth in GB/s | CDN, egress cost becomes a first-class concern |
| cache working set > one node’s RAM | Redis cluster, or cache only the hot tail |
| spiky writes | queue between API and DB to absorb the spike |
The whole point of the phase: let the arithmetic pick the architecture, then justify the architecture by pointing back at the arithmetic.
Interview angle
- “Estimate the QPS for [system].” — DAU × actions-per-user-per-day ÷ ~100k seconds, then ×2-3 for peak. Say the assumptions out loud; round aggressively.
- “How much storage will this need?” — items/day × bytes/item × retention. Then sanity-check the magnitude — TB vs PB changes everything.
- “Why does the read:write ratio matter?” — it decides where the engineering effort goes. Very read-heavy → caching, replicas, denormalization, fan-out-on-write. Write-heavy → queues, partitioned writes, fan-out-on-read.
- “Your estimate came out to X — so what?” — that’s the real question. The number must drive a decision: “40 write QPS means one primary suffices — I won’t shard,” or “15 GB/s bandwidth means this is a CDN problem.” An estimate with no consequence is wasted time.
- “You don’t know the exact numbers.” — that’s expected. State a reasonable assumption, do the arithmetic on it, and note that the interviewer can adjust the input. The method is what’s scored.