Back to Notes

Back-of-Envelope Estimation

Why It Matters

Capacity math is step 2 of every HLD ([[SD Interview Framework & Pitfalls]]). Point isn't a precise number — it's justifying architecture. "Writes fit on one Postgres box" vs "writes need sharding + a queue" is decided by one QPS calc. Skip the math → every later decision is a guess. Interviewer watches whether the numbers drive the design, not the arithmetic.

Round hard. 86,400 s/day ≈ 100,000. 1 million ≈ 2^20. Goal is right order of magnitude, fast.

The One Discipline That Prevents 90% of Estimation Failures

The interviewer stops trusting every number the moment one doesn't foot. Two rules:

  1. Write the exponent explicitly, every time. Not "100M × 365." Write 10⁸ × 365 ≈ 3.65 × 10¹⁰. When multiplying two powers of ten, do the exponents first (add them), then the mantissas — 2×10⁷ × 5×10⁶ → 7+6=13, 2×5=10 → 10¹⁴. Powers of ten are where everyone's error rate spikes.
  2. When you correct any input, re-run every calc that consumed it before moving on. The classic failure: fix "36.5B → 365B" on the board but leave storage at the old "18 TB." One stale number poisons the whole board.
  3. Smell-test the top-line before building down. 10M tweets/day for global Twitter should smell wrong (real ≈ 500M/day). A 5-second gut check catches a 30× base-number miss before three steps compound it.

Say your numbers back as powers of ten out loud: "ten-to-the-eight per day, times three-six-five, is three-six-five times ten-to-the-ten." The verbal check catches the slip the mental math misses.

Numbers to Memorize

Powers of 10 (QPS / counts)

NameValueSymbol
Thousand10³K
Million10⁶M
Billion10⁹B / G
Trillion10¹²T
Quadrillion10¹⁵P

Multiplying/dividing = add/subtract exponents. 10⁸ / 10⁵ = 10³. That's the whole trick for QPS.

Powers of 2 → data size

PowerValueNameNote
2^10~1 thousandKB
2^20~1 millionMB
2^30~1 billionGB
2^324.3×10⁹IPv4 space, unsigned int max
2^40~1 trillionTB
2^50~1 quadrillionPB
2^641.8×10¹⁹Snowflake / bigint

Time → seconds (the QPS denominators)

1 day   = 86,400 s     ≈ 10^5 s   (round to 100k)
1 month ≈ 2.5 million s ≈ 2.5×10^6 s
1 year  ≈ 31.5 million s ≈ 3×10^7 s
  • X per day → per second: ÷ 10⁵. 100M/day = 10⁸/10⁵ = 1,000/s (precise 1,157 — say the round-down).
  • X per day → per year: × 3.65×10². 10⁸ × 365 = 3.65×10¹⁰ = 36.5B/year. Per 10yr = 365B.
  • Peak factor: × 2–3× avg. State it; never design to the average.

Data sizes

UnitBytesFieldTypical size
1 char (ASCII)~1 BBool / small int1–4 B
1 KB10³ BLong / timestamp8 B
1 MB10⁶ BUUID16 B
1 GB10⁹ BShort code (7 char)7 B
1 TB10¹² BTweet / short text~140–280 B
1 PB10¹⁵ BURL (long)~100–500 B (use 400–500 B)

Latency ladder (Jeff Dean — memorize the ratios, not digits)

OpTime
L1 cache ref0.5 ns
Mutex lock/unlock25 ns
Main memory ref100 ns
Compress 1 KB3 µs
SSD random read150 µs
Send 1 KB over 1 Gbps10 µs
Read 1 MB sequentially from memory250 µs
Round trip within datacenter500 µs
Read 1 MB sequentially from SSD1 ms
Disk (HDD) seek10 ms
Read 1 MB from disk20 ms
Packet round trip CA↔Netherlands150 ms

Takeaways that win points: memory ~100k× faster than disk seek → cache hot data. Cross-continent RTT (150 ms) dwarfs everything → co-locate, don't chat across regions. SSD ~100× faster random read than HDD → why nobody spins disks for OLTP.

The Estimation Recipe

Always the same 5 quantities, in order. Announce each subtotal. If you correct step 1, re-do steps 2–4.

  1. DAU → QPS. QPS_avg = (DAU × actions/user/day) / 86,400. Then QPS_peak ≈ 2–3 × QPS_avg.
  2. Read:write ratio. State it explicitly (100:1 feed, 1:1 chat). Drives whether you optimize reads (cache/replicas) or writes (queue/shard).
  3. Storage = objects/day × size/object × retention. Multiply out to 5 years for the "do we shard" answer.
  4. Bandwidth = QPS × payload size. Split ingress vs egress; egress is what CDN offloads. Bitrate is bits, storage is bytes — the 8× trap lives here.
  5. Memory for cache. 80/20 rule — cache the hot 20%. cache_size = 0.2 × hot_key_count × object_size. Sanity-check vs RAM per node.

Base62 Keyspace (URL shortener / ID length)

LengthValue~Power
62⁵916 M~10⁹
62⁶56.8 B~5.7×10¹⁰
62⁷3.52 T~3.5×10¹²
62⁸218 T~2.2×10¹⁴

Pick length so keyspace ≫ total records over retention. 62⁷ (3.5T) vs 365B needed → ~10× headroom → 7 chars. 62⁶ (57B) < 365B → 6 fails.

Worked Example 1 — Twitter-scale Feed

Given: 300M DAU, 2 tweets/day/user, reads timeline 50×/day, tweet ≈ 1 KB (text + metadata), 5-year retention.

# 1. QPS
writes/day = 300M × 2        = 600M
reads/day  = 300M × 50       = 15B
write QPS_avg = 600M / 86,400 ≈ 7,000
read  QPS_avg = 15B  / 86,400 ≈ 170,000
peak read QPS ≈ 3 × 170k      ≈ 500,000

# 2. Ratio
read:write ≈ 25:1  → read-heavy → fan-out + cache, replicas for reads

# 3. Storage
writes/day × size = 600M × 1 KB = 600 GB/day
5-year = 600 GB × 365 × 5       ≈ 1.1 PB   → must shard, cold storage tiering

# 4. Bandwidth
read egress = 170k QPS × 1 KB   ≈ 170 MB/s  ≈ 1.4 Gbps steady → CDN/edge cache

# 5. Cache (hot 20% of reads)
0.2 × 15B reads × 1 KB          = 3 TB hot set → distributed Redis cluster, not one box

Design conclusions the numbers forced: read-heavy 25:1 → precompute timelines (fan-out on write) + heavy caching; 1.1 PB → shard by user_id, tier old tweets to blob storage; 3 TB hot set → Redis cluster, sharded, not a single instance.

Worked Example 2 — URL Shortener @ 100M writes/day

TRAFFIC
  Writes: 100M/day = 10⁸ / 10⁵ s     = 1,000/s   (precise 1,157; peak ×3 ≈ 3K/s)
  Reads:  100:1     = 10¹⁰/day = 10⁵/s = 100,000/s (peak ×3 ≈ 300K/s)
  → All design pressure is on the READ path. Say this sentence.

RECORDS
  Per year:  10⁸ × 365 = 3.65 × 10¹⁰ = 36.5 B/year
  Per 10yr:  × 10       = 3.65 × 10¹¹ = 365 B          ← the number to get right

CODE LENGTH (base62)
  Need > 365B codes.
  62⁶ = 57B   < 365B  → 6 FAILS
  62⁷ = 3.5T  / 365B ≈ 10× headroom → 7 chars ✅

STORAGE
  365 × 10⁹ records × 500 B = 1.8 × 10¹⁴ B = 182 TB
  (small enough to fit on a handful of nodes → shard for throughput, not capacity)

BANDWIDTH
  Read:  10⁵/s × 500 B = 5 × 10⁷ = 50 MB/s   (trivial)
  Write: 10³/s × 500 B = 5 × 10⁵ = 500 KB/s   (trivial)

CACHE (Pareto 80/20)
  Cache hot code→URL only (~400 B, drop metadata).
  Few hundred M hot entries × 400 B ≈ 150–200 GB Redis, cache-aside + LRU.

Note: canonical [[Design a URL Shortener]] uses a 10M/day assumption (→ 9 TB / 5 yr); this example uses 100M/day. Both are internally consistent — the point is the method. Always restate the assumption you picked.

Availability — The Nines

AvailabilityDowntime / yearDowntime / day
99%3.65 days14.4 min
99.9% ("three nines")8.76 hours1.44 min
99.99% ("four nines")52.6 min8.6 s
99.999% ("five nines")5.26 min0.86 s

Sanity-Check Anchors

Ballpark ceilings to catch nonsense answers:

ResourceRough single-node ceiling
Postgres/MySQL writes~10k simple writes/s per node
Redis ops~100k ops/s per instance
Single server RAM64–256 GB typical
NIC bandwidth10 Gbps ≈ 1.25 GB/s
SSD sequential read~500 MB/s–3 GB/s
Kafka partition~10 MB/s or ~10k msg/s

If your calc says "1 Postgres node does 500k writes/s," you rounded wrong or need sharding.

Interview Drill

Q: You estimate 500k peak read QPS. Walk me from that number to a concrete component decision. A: 500k QPS × 1 KB ≈ 500 MB/s egress — one NIC (10 Gbps ≈ 1.25 GB/s) survives but leaves no headroom, and one DB node (~10k reads/s) is 50× short. So: read replicas alone won't cut it (need ~50) → cache in front sized to the hot set, serve the 80% hit rate from Redis, and only the ~100k QPS miss traffic touches replicas. The QPS number directly sized both the cache tier and the replica count.

Q: When do you skip the estimation? A: Never skip it, but keep it to 2 minutes. Even a rough calc that says "this fits on one box" is a result — it tells you not to over-engineer. The mistake is silent hand-waving, not spending too long.

Self-Drill (redo cold, under 4 min each, exponents written out)

  1. Twitter feed: 500M DAU, 2 tweets/day, each read 100×. Tweets/s? Reads/s? Storage/year at 300 B/tweet?
  2. Chat app: 50M DAU, 40 messages/user/day, 100 B/message. Messages/s at peak? Storage/year?
  3. Video platform: 1M videos/day, avg 100 MB each. Storage/day? /year? Egress if each watched 1000× at 5 MB streamed?
  4. Rate limiter: 1B requests/day across the fleet. Requests/s? 16 B/counter × 100M users → memory?
  5. URL shortener redo: the Worked Example 2 numbers from scratch, no peeking. Check every power of ten.

Grading rule (self): any single 10× slip = fail the drill, redo it. That's the whole point.

Cross-links

[[SD Interview Framework & Pitfalls]] · [[Core Vocabulary & Quality Pillars]] · [[Latency vs Throughput]] · [[Caching & Redis]] · [[Database Replication & Sharding]] · [[News Feed - Twitter Feed]] · [[Design a URL Shortener]] · [[Design a Unique ID Generator]] · [[Design a Distributed Key-Value Store]] · [[Rate Limiter]]