system-design

Back-of-the-Envelope Estimation ⭐

The highest-leverage skill in system design. Ten minutes of arithmetic tells you whether you need three servers or three thousand — and interviewers can spot who can do it in about ninety seconds.

Prerequisites: Latency Numbers Time to read: ~30 minutes. Then practise for a week.


Why this chapter matters more than the others

Every architectural decision is downstream of scale:

If you can’t estimate, you’re guessing. And an interviewer who watches you propose Kafka, sharding, and multi-region for a system that runs at 40 QPS has learned something important about you.

The reverse is even more valuable. When you say “that’s 500 GB a year, which fits on one machine for the next three years, so I’d start with a single Postgres and revisit at 10× growth” — you have just demonstrated engineering judgment, cost awareness, and the ability to resist over-engineering, all in one sentence.


The rules

1. Round aggressively. You want the right order of magnitude, not accuracy. 86,400 becomes 100,000. 365 becomes 400. 8 bytes becomes 10. Nobody will challenge you; everyone will be relieved.

2. Use powers of ten. Convert everything to scientific notation and the arithmetic becomes addition of exponents.

3. State every assumption out loud. “I’ll assume 100 million daily active users, and that each opens the app 10 times a day.” Interviewers correct wrong assumptions and reward stated ones. A silent estimate is unverifiable and worthless.

4. Show the units. bytes/day, requests/second, GB. Unit errors are the only errors that matter, and carrying units catches them automatically.

5. Sanity-check against reality. If your estimate says a photo-sharing app needs 40 exabytes a year, you made an error. Compare to things you know: the whole of Wikipedia’s text is ~25 GB, a large company’s database is single-digit TB.


The numbers you must have memorized

Time:

Seconds per day      = 86,400  ≈ 10⁵     ← the most important approximation in this chapter
Seconds per month    ≈ 2.5 × 10⁶
Seconds per year     ≈ 3 × 10⁷

The magic conversion:

1 million/day    ≈ 12 QPS       (10⁶ / 10⁵ = 10)
10 million/day   ≈ 116 QPS      (call it 100)
100 million/day  ≈ 1,160 QPS    (call it 1,000)
1 billion/day    ≈ 11,600 QPS   (call it 10,000)

Once you know 1 M/day ≈ 10 QPS, you can convert any daily figure in your head instantly.

Powers of two, for storage:

2¹⁰ = 1 thousand   = 1 KB
2²⁰ = 1 million    = 1 MB
2³⁰ = 1 billion    = 1 GB
2⁴⁰ = 1 trillion   = 1 TB
2⁵⁰ = 1 quadrillion = 1 PB

Typical object sizes:

A tweet / short text post   ~300 bytes  →  round to 1 KB with metadata
A JSON API response         1–10 KB
A user record               ~1 KB
A thumbnail                 ~50 KB
A photo                     ~2 MB
A minute of 1080p video     ~50 MB

Single-machine capacities (rough, for sanity-checking):

One modern server:      8–64 cores, 32–256 GB RAM, 1–10 Gbps NIC
One Postgres instance:  ~10–50k simple QPS, comfortably up to a few TB
One Redis instance:     ~100k ops/sec, RAM-limited
One Kafka broker:       ~100 MB/s–1 GB/s
One app server:         1k–10k QPS depending on language and work

The recipe

Do these six steps, in order, every time:

1. USERS       →  DAU, and requests per user per day
2. QPS         →  average, then peak (× 2–3)
3. STORAGE     →  bytes per item × items per day × retention
4. BANDWIDTH   →  QPS × payload size
5. MEMORY      →  what fraction is hot? (80/20 rule)
6. MACHINES    →  divide by per-machine capacity

Then interpret: what does this tell me about the architecture? That last step is what separates estimation from arithmetic.


Worked example 1: Twitter

The classic. Let’s do it properly.

Step 1 — Users and actions

Assumption: 300 M monthly active users
Assumption: 50% are daily active        →  DAU = 150 M
Assumption: each user posts 2 tweets/day →  300 M tweets/day
Assumption: each user reads 100 tweets/day → 15 B tweet-reads/day

🎙️ Say this out loud: “I’ll assume 150 million daily actives, posting twice a day and reading a hundred tweets a day. That gives a read:write ratio of about 50:1, which already tells me this is a read-heavy system and the design should optimize for reads.”

That last sentence is the whole point. You extracted an architectural insight from three assumptions.

Step 2 — QPS

Writes:  300 M / 10⁵   =  3,000 QPS  average
Peak (×3)              =  9,000 QPS

Reads:   15 B / 10⁵    =  150,000 QPS average
Peak (×3)              =  450,000 QPS

Interpretation: 9,000 writes/sec is significant but manageable — a sharded database handles it. 450,000 reads/sec absolutely cannot come from a database. That number forces caching and precomputation into the design. You now know you need a feed cache, and you can say why.

Step 3 — Storage

Per tweet:
  text            280 chars ≈ 300 bytes
  metadata        (id, user_id, timestamp, counts) ≈ 200 bytes
  round up to     1 KB per tweet (generous, covers indexes)

Daily:   300 M tweets × 1 KB     = 300 GB/day
Yearly:  300 GB × 365            ≈ 110 TB/year
5 years:                         ≈ 550 TB

Media (assume 10% of tweets have an image at 2 MB):
  30 M images/day × 2 MB         = 60 TB/day     ← 200× the text!
  Yearly                         ≈ 22 PB/year

Interpretation: two completely different storage problems. Text is ~110 TB/year — big, needs sharding, but ordinary. Media is 22 PB/year and belongs in object storage behind a CDN, never in your database.

🚨 Noticing that media dwarfs text by 200× is exactly the kind of observation that scores points.

Step 4 — Bandwidth

Write:   3,000 tweets/s × 1 KB       = 3 MB/s        (trivial)
Media:   350 images/s × 2 MB         = 700 MB/s      = 5.6 Gbps
Read:    150,000 reads/s × 1 KB      = 150 MB/s      = 1.2 Gbps

Interpretation: media upload alone needs 5.6 Gbps. One server has 1–10 Gbps. Media must be uploaded directly to object storage (pre-signed URLs), not proxied through your app servers.

Step 5 — Memory for cache

Apply the 80/20 rule: 20% of tweets generate 80% of reads. And people mostly read recent tweets.

Cache the last 3 days of tweets:
  300 M/day × 3 days × 1 KB   = 900 GB

Or cache 20% of daily tweets:
  300 M × 0.2 × 1 KB          = 60 GB/day of hot content

Interpretation: ~900 GB doesn’t fit on one machine, so you need a distributed cache — which means consistent hashing. But it’s only ~10 machines with 128 GB each, which is very affordable. Cache is clearly the right answer here.

Step 6 — Machines

Read servers:  450,000 peak QPS ÷ 5,000 QPS per server  = 90 servers
Write servers: 9,000 peak QPS ÷ 2,000 QPS per server    = 5 servers
Cache:         900 GB ÷ 128 GB per node                 = ~8–10 nodes (+ replicas)
Database:      550 TB ÷ 2 TB per shard                  = ~275 shards

The payoff

From ten minutes of arithmetic you now know, with justification:

You have derived the architecture from the numbers, rather than pattern-matching to a diagram you saw once. That’s the difference the interviewer is looking for.


Worked example 2: a URL shortener

A deliberately smaller system, to show that estimation also tells you when not to build things.

Assumption: 100 M new URLs/month
Reads:      100:1 read/write ratio → 10 B redirects/month

Writes: 100 M / (30 × 10⁵)  ≈ 33 QPS      ← tiny
Reads:  10 B / (30 × 10⁵)   ≈ 3,300 QPS   ← modest
Peak reads (×3)             ≈ 10,000 QPS

Storage per record:
  short code    7 bytes
  long URL      ~100 bytes
  metadata      ~50 bytes
  round to      500 bytes

Monthly:  100 M × 500 B  = 50 GB/month
5 years:  50 GB × 60     = 3 TB

Cache: 20% of URLs serve 80% of traffic
  Daily reads: 10 B/30 = 333 M/day
  Hot set: 20% of a month's URLs = 20 M × 500 B = 10 GB

Interpretation — and this is the valuable part:

🎙️ “The numbers say this fits comfortably on one database with a read replica and a single Redis cache for the next several years. I’d start there rather than sharding on day one, and revisit if we see 10× growth.”

That answer beats a sharded, multi-region design. Recognizing when the simple thing suffices is a senior signal, and estimation is how you prove it rather than assert it.


Worked example 3: video streaming

Assumption: 500 M DAU, each watches 30 min/day of 1080p
1080p bitrate ≈ 5 Mbps

Total watch time:  500 M × 30 min = 15 B minutes/day = 250 M hours/day

Bandwidth (peak concurrent viewers):
  Assume 10% of DAU watching at peak = 50 M concurrent
  50 M × 5 Mbps = 250 Tbps                       ← !!

Storage (uploads):
  Assume 500 hours uploaded per minute
  = 720,000 hours/day
  1 hour of 1080p ≈ 2 GB, but you store ~5 encodings (240p–4K) ≈ 6 GB total
  720,000 × 6 GB = 4.3 PB/day  ≈ 1.6 EB/year

Interpretation:

Notice how one number (250 Tbps) determined the entire architecture.


Common estimation patterns

Read/write ratio. Always compute it. It’s the single most architecture-determining number.

Ratio Implication
1:1 Balanced; optimize both paths
10:1 read-heavy Add caching and read replicas
100:1 read-heavy Precompute/denormalize; cache is mandatory
Write-heavy (1:10) LSM-based store, batching, async processing, queue in front

Peak vs average. Multiply average by:

🚨 Ask about this. “Is traffic steady, or is there a spike — like a flash sale?” If it spikes, the design changes completely: you need queues, rate limiting, and load shedding, not just more servers.

The 80/20 rule. 20% of your data serves 80% of traffic. Use it to size caches. (For social apps it’s often more extreme — 1% of content gets 90% of views.)

Storage growth. Always project to 3–5 years, not today. A design that works today and dies in eight months isn’t a design.

Replication multiplier. Real storage = raw × replication factor (usually 3) × index overhead (~1.2×) ≈ 3.6× your raw number. Mention it; most candidates forget.


Cost estimation (the thing almost nobody does)

Rough public-cloud figures, good enough for an order of magnitude:

Resource Approx. cost
Compute (mid-size VM) ~$70/month
Block storage (SSD) ~$0.10/GB/month
Object storage (S3-class) ~$0.023/GB/month
Egress bandwidth to internet ~$0.05–0.09/GB ← usually the surprise
Managed database 2–3× the raw VM cost
CDN egress ~$0.01–0.05/GB (cheaper than origin egress)

📐 The classic revelation: for the Twitter example, serving 150 MB/s of reads = ~390 TB/month of egress = ~$25,000/month in bandwidth alone. Storage of 110 TB/year in S3 is ~$2,500/month. The bandwidth costs 10× the storage.

🎙️ “Egress is going to dominate our cost here, not storage or compute — which is another argument for a CDN, since CDN egress is meaningfully cheaper than origin egress and it also cuts our origin traffic.”

Bringing up cost unprompted is one of the strongest senior signals available in a design interview. Almost nobody does it.


🚨 Interview traps


🎙️ Soundbites


🛠️ Try it

Estimate these before reading any solution. Give yourself 5 minutes each, out loud, writing down assumptions:

  1. WhatsApp. 2 B users. How many messages per second? How much storage per year if messages aren’t deleted?
  2. Google Search. How many queries per second? How much storage for an index of the web?
  3. Uber/Careem. 100 M users, 20 M rides/day. Driver location updates every 4 seconds — what’s the write QPS for locations? (This one has a surprising answer.)
  4. Your university’s portal. 20,000 students. What’s the peak QPS on results day, and how many servers do you need?
  5. Instagram. How much storage for photos per year? How much bandwidth at peak?

Then check yourself against Estimation Drills, which has 50 of these with full solutions.

A daily habit worth building: every time you use an app, estimate its scale. Waiting for coffee? Estimate Netflix’s storage. It takes two minutes and it makes this automatic.


Check yourself

1. 500 million requests per day. Average QPS? Peak? 500 M / 10⁵ = **5,000 QPS** average. Peak at 2–3× = **10,000–15,000 QPS**. (Exact: 500,000,000 / 86,400 = 5,787 — the rounded answer is fine and much faster.)
2. Users upload 10 million photos a day at 3 MB each. Storage per year, including 3× replication? 10 M × 3 MB = 30 TB/day. × 365 ≈ **11 PB/year raw**. With 3× replication ≈ **33 PB/year**. Add thumbnails and multiple resolutions (typically +30–50%) and you're near 45 PB. Interpretation: this is object storage territory, with lifecycle policies to move old photos to cold tiers.
3. Why is peak traffic more important than average for capacity planning? Because you must be up at peak. Provisioning for average means being overloaded for several hours every day. The multiplier depends on the product: 2–3× for a global consumer app whose users are spread across time zones, but 10× or more for a regionally-concentrated app with a sharp usage window (food delivery at 8pm), and 100×+ for event-driven spikes like ticket sales. Ask which you're dealing with — it changes whether you need autoscaling, queues, or load shedding.
4. A social app has 100:1 read-to-write. What three design decisions does that immediately imply? (1) Cache aggressively — reads dominate, so hit rate governs everything. (2) Add read replicas so reads never touch the primary. (3) Denormalize/precompute — do expensive work once at write time so the 100 reads are cheap (this is the fan-out-on-write argument). Also worth saying: you can afford expensive writes, because there are 100× fewer of them.
5. Your estimate says you need 3 PB of storage. Sanity-check it — what should you compare against? Compare to known quantities. All of Wikipedia's text is ~25 GB; the entire English Wikipedia with media is ~100 TB. A large enterprise's transactional database is single-digit TB. 3 PB is 30× all of Wikipedia — plausible *only* if you're storing media (photos/video) at consumer scale. If your system stores text records and you got 3 PB, recheck: you probably inflated a per-record size or a volume assumption by 1000×.

Further reading