ARTICLE · Playbook
Back-of-the-Envelope Numbers
Derived: memory is ~100x faster than SSD random reads; SSD is ~100x faster than HDD seeks; same-DC RTT is ~300x faster than intercontinental. Avoid disk seeks; read sequentially; compress before sending over WAN…
Latency numbers every programmer should know (Dean/Norvig, ~2020 revisions)#
| Operation | Latency | Said as |
|---|---|---|
| L1 cache reference | ~1 ns | "a nanosecond" |
| Branch mispredict | ~3-5 ns | |
| L2 cache reference | ~4-7 ns | |
| Mutex lock/unlock (uncontended) | ~20-25 ns | |
| Main memory reference | ~100 ns | "a hundred nanoseconds" |
| Compress 1 KB with Snappy/Zippy | ~2-3 µs | |
| Send 1 KB over 1 Gbps network | ~10 µs | |
| Read 4 KB randomly from SSD | ~100-150 µs | "a hundred microseconds" |
| Read 1 MB sequentially from memory | ~250 µs | "a quarter millisecond" |
| Round trip within same datacenter | ~500 µs | "half a millisecond" |
| Read 1 MB sequentially from SSD | ~1 ms | |
| Disk seek (HDD) | ~10 ms | |
| Read 1 MB sequentially from HDD | ~20-30 ms | |
| Send packet CA → Netherlands → CA | ~150 ms | "cross-Atlantic round trip" |
Derived: memory is ~100x faster than SSD random reads; SSD is ~100x faster than HDD seeks; same-DC RTT is ~300x faster than intercontinental. Avoid disk seeks; read sequentially; compress before sending over WAN (compression is cheap vs network).
Powers of two and sizes#
| Power | Approx | Name |
|---|---|---|
| 2^10 | 1 thousand | 1 KB |
| 2^20 | 1 million | 1 MB |
| 2^30 | 1 billion | 1 GB |
| 2^40 | 1 trillion | 1 TB |
| 2^50 | 1 quadrillion | 1 PB |
| 2^32 | 4.3 billion | IPv4 space, 32-bit int |
| 2^64 | 1.8 × 10^19 | 64-bit int, Snowflake range |
Sizes to quote: ASCII char 1 B; int 4 B; long/timestamp 8 B; UUID 16 B (36 chars as text); a tweet-sized text ~300 B; a typical row/JSON record ~1 KB; a thumbnail ~10-50 KB; a photo ~200 KB-2 MB (say 300 KB-1 MB); 1 min of 1080p video ~50-100 MB; a web page with assets ~2 MB.
Time and QPS rules of thumb#
- Seconds/day = 86,400 ≈ 10^5 (use 100k for mental math; it overestimates QPS by ~15%, which is conservative).
- Seconds/month ≈ 2.6M ≈ 2.5 × 10^6; seconds/year ≈ 31.5M ≈ 3 × 10^7.
- 1M requests/day ≈ 12 QPS. 100M/day ≈ 1,160 QPS. 1B/day ≈ 11,600 QPS. 10B/day ≈ 116k QPS.
- 1M DAU × 10 requests/day = 10M/day ≈ 115 QPS average.
- Peak = 2-5x average (say 3x unless told otherwise). Design for peak, not average.
- Read:write ratio: 10:1 typical for social/content; 100:1 for read-heavy catalogs; ~1:1 for chat/logging.
- Storage/year = writes/day × bytes × 365; always state retention (1, 5, 10 years) and replication factor (×3).
- Bandwidth = QPS × payload size; 1 Gbps = 125 MB/s; 10 Gbps = 1.25 GB/s.
Typical single-node capacities (order of magnitude; say "roughly")#
| Component | Capacity |
|---|---|
| Postgres / MySQL primary | thousands to low tens of thousands of writes/s; tens of thousands of indexed reads/s; comfortable to a few TB |
| Redis (single node) | ~100k ops/s simple commands; ~1M with pipelining; sub-ms; RAM-bound |
| Memcached | hundreds of thousands to ~1M ops/s per node (multithreaded) |
| Cassandra / ScyllaDB node | ~10k-20k writes/s per node (Scylla much higher); linear scale with nodes |
| Kafka broker | ~100k+ msgs/s; cluster into millions/s; single partition ~10-50 MB/s |
| Nginx / HAProxy / Envoy | tens of thousands of req/s per core; L4 handles millions of connections |
| App server (Node/Go/Java), simple handler | thousands to tens of thousands req/s; with real business logic + DB calls, ~500-2,000 req/s per instance |
| WebSocket gateway | ~100k-1M idle connections per node |
| Elasticsearch node | thousands of docs/s indexing; ms-level search on tens of GB per shard (keep shards 10-50 GB) |
| SSD | ~100k random IOPS; ~500 MB/s-3 GB/s sequential. HDD: ~100-200 IOPS; ~100-200 MB/s |
| Cloud object storage (S3) | 3,500 PUT/s and 5,500 GET/s per prefix; 11 nines durability |
Availability math#
| Nines | Downtime / year | / month | / day |
|---|---|---|---|
| 99% | 3.65 days | 7.3 h | 14.4 min |
| 99.9% | 8.76 h | 43.8 min | 1.44 min |
| 99.95% | 4.38 h | 21.9 min | 43 s |
| 99.99% | 52.6 min | 4.38 min | 8.6 s |
| 99.999% | 5.26 min | 26.3 s | 0.86 s |
- Series (A depends on B): multiply. 0.999 × 0.999 = 0.998. Ten 99.9% dependencies in series ≈ 99.0%.
- Parallel (either works): 1 − (1−a)^n. Two 99.9% nodes = 99.9999%. Three 99% nodes = 99.9999%.
- Availability = MTBF / (MTBF + MTTR): cutting MTTR is usually cheaper than raising MTBF.
Worked example: Twitter-like feed#
Assumptions (say them): 300M MAU, 50% daily → 150M DAU; 2 posts/user/day; 10% of posts have 1 MB media; 5-year retention; feed reads 10/user/day.
Write QPS: 150M × 2 / 86,400 ≈ 3,500 posts/s peak ×2 ≈ 7,000Read QPS: 150M × 10 / 86,400 ≈ 17,400 feed reads/s peak ×2 ≈ 35,000Text storage: 300M posts/day × ~300 B (text+meta) ≈ 90 GB/day ≈ 33 TB/yr ≈ 165 TB / 5 yr (×3 replicas ≈ 500 TB)Media: 300M × 10% × 1 MB = 30 TB/day ≈ 11 PB/yr ≈ 55 PB / 5 yr → object storage + CDN, tiered to coldBandwidth: media 30 TB/day ÷ 86,400 ≈ 350 MB/s ingress; reads several × that egress via CDNFeed cache: 150M users × 500 post IDs × 8 B = 600 GB → Redis cluster, ~10-20 nodes of 64 GB with overheadFan-out: 3,500 posts/s × 200 followers avg = 700k feed inserts/s → Kafka + workers; celebrities via pullConclusion sentence: "Writes fit a sharded Postgres or Cassandra; reads are cache-dominated; media is 99% of bytes and lives in S3 behind a CDN; the fan-out is the hard part."
Mental math shortcuts#
- Divide by 86,400 ≈ divide by 100k then add 15%. 100M/day → ~1,000 → ~1,160 QPS.
- Multiply by 365 ≈ ×400 then subtract 10%. 90 GB/day → 36 TB → ~33 TB/yr.
- 1 KB × 1M = 1 GB; 1 KB × 1B = 1 TB; 1 MB × 1M = 1 TB.
- 1 QPS sustained for a day ≈ 86k requests ≈ 10^5.
- Keep 2 significant figures; say "order of magnitude."
See also