11 min read
System Design Index
Start Here
Tier 1 -- Building Blocks
Scale Reads
Scale Writes
Database Selection
Traffic Control
Consistency & Coordination
Estimation
Tier 2 -- Core Systems
Tier 3 -- Location & Real-Time
Tier 4 -- Infrastructure & Data
Tier 5 -- Finance & Commerce
Tier 6 -- Advanced & Collaborative
System Design Index
Start Here
Tier 1 -- Building Blocks
Scale Reads
Scale Writes
Database Selection
Traffic Control
Consistency & Coordination
Estimation
Tier 2 -- Core Systems
Tier 3 -- Location & Real-Time
Tier 4 -- Infrastructure & Data
Tier 5 -- Finance & Commerce
Tier 6 -- Advanced & Collaborative
Back-of-the-Envelope Estimation
1. What Is It?
Back-of-the-envelope (BOTE) estimation is the practice of quickly approximating the scale, capacity requirements, and performance characteristics of a system using rough mental math. In a system design interview, the purpose is not to get exact numbers — it's to make informed architecture decisions. "Is this read-heavy or write-heavy? Do I need ? Can this fit in a single database? Do I need a ?"
The estimation phase answers these questions in 5–10 minutes, producing numbers accurate to within an order of magnitude. Decisions made from these numbers are directionally correct even if the exact values are off by 2–3x. The math drives architecture choices — don't calculate for the sake of it; calculate to make a decision.
During a system design discussion, an engineer estimates that their service will receive 50,000 requests per second and calculates that a single database instance can handle roughly 20,000 queries per second. The engineer's estimate might be off by 2–3x in either direction. What is the most appropriate action to take based on this estimation?
2. The Mental Math Toolkit
Power of 2 (Binary Prefixes)
| Power | Approx Value | Name |
|---|---|---|
| 2¹⁰ | ~1,000 | 1 KB |
| 2²⁰ | ~1,000,000 | 1 MB |
| 2³⁰ | ~1,000,000,000 | 1 GB |
| 2⁴⁰ | ~1,000,000,000,000 | 1 TB |
| 2⁵⁰ | ~1,000,000,000,000,000 | 1 PB |
Latency Reference Numbers (Approximate, 2024)
| Operation | Latency | Notes |
|---|---|---|
| L1 cache hit | ~1 ns | In-CPU |
| L2 cache hit | ~4 ns | In-CPU |
| L3 cache hit | ~10 ns | In-CPU |
| Main memory (RAM) access | ~100 ns | |
| SSD random read | ~100 µs (0.1ms) | |
| Spinning disk seek | ~5–10 ms | Avoid in hot paths |
| Redis GET (same datacenter) | ~0.1–0.5 ms | Network round-trip included |
| PostgreSQL query (indexed, no join) | ~1–5 ms | |
| Network round-trip (same datacenter) | ~0.5–1 ms | |
| Network round-trip (same region) | ~1–5 ms | |
| Network round-trip (cross-continent) | ~50–150 ms |
Key Numbers to Know
| Fact | Value |
|---|---|
| Seconds per day | 86,400 ≈ 100K |
| Seconds per year | ~31.5M ≈ 30M |
| 1 char (ASCII) | 1 byte |
| 1 char (UTF-8 common) | 1–3 bytes |
| 1 int (32-bit) | 4 bytes |
| 1 long / int64 | 8 bytes |
| 1 UUID | 16 bytes |
| 1 MD5 hash | 16 bytes |
| 1 SHA-256 hash | 32 bytes |
| Average tweet (text) | ~140 bytes |
| Average web page | ~100 KB |
| Average JPEG photo | ~300 KB |
| 1080p image (uncompressed) | ~6 MB |
| 1-minute video (1080p H.264) | ~100–300 MB |
| 1-minute video (4K) | ~500 MB–1 GB |
3. Estimation Templates
Template 1: QPS (Queries Per Second)
DAU (Daily Active Users)
↓
Average requests per user per day
↓
Total daily requests = DAU × requests/user
↓
Average QPS = total_daily / 86,400 (divide by ~100K for rough estimate)
↓
Peak QPS = average QPS × 2–5 (peak is typically 2–5x average)
↓
Decision: can a single server handle this? (typical web server: 5K–50K req/s)
do I need multiple servers? caching? CDN?
Example: Twitter-like system
DAU = 150M users
Average timeline refreshes per user per day = 10
Total reads/day = 150M × 10 = 1.5B reads/day
Average read QPS = 1.5B / 100K = 15,000 QPS
Peak read QPS ≈ 15,000 × 3 = 45,000 QPS (3x for peak hour)
Total writes/day (tweets) = 150M users × 0.1 tweets/user = 15M tweets/day
Average write QPS = 15M / 100K = 150 QPS
Peak write QPS ≈ 150 × 3 = 450 QPS
Conclusion: Read-heavy (100:1 ratio). Reads need caching and read replicas.
Writes are modest — single primary handles 450 QPS easily.
Template 2: Storage
Storage per item = (metadata fields × field sizes) + media size
↓
Daily storage growth = items_written_per_day × storage_per_item
↓
Annual storage = daily × 365 ≈ daily × 400 (round up for safety)
↓
5-year storage = annual × 5
↓
Decision: does this fit in one database? Do I need object storage (S3)?
Do I need tiered storage (hot/warm/cold)?
Example: Instagram-like photo storage
Photos uploaded per day = 10M
Average compressed JPEG size = 300 KB
Daily storage = 10M × 300 KB = 3 TB/day
Annual storage = 3 TB × 400 = 1.2 PB/year
5-year storage = 6 PB
Conclusion: Definitely need object storage (S3/GCS), not a database.
CDN for frequently accessed photos.
Consider tiered storage: hot (last 30 days), cold (older).
Template 3: Bandwidth
Inbound bandwidth = write QPS × average_request_size
Outbound bandwidth = read QPS × average_response_size
↓
Decision: is this within typical datacenter egress limits?
Do I need a CDN to reduce origin bandwidth?
Example: Video streaming (YouTube-like)
Concurrent streams = 5M users watching at any given time
Average video bitrate = 5 Mbps (1080p H.264)
Outbound bandwidth = 5M × 5 Mbps = 25 Tbps
Conclusion: No single datacenter handles 25 Tbps.
CDN is absolutely mandatory — CDN edge nodes serve video,
not the origin. Origin handles uploads only.
Template 4: Cache Size
Working set = "hot" data that accounts for 80% of reads (Pareto principle)
↓
Cache size estimate = working_set_size × safety_factor (1.5–2x)
↓
Check: does this fit in RAM on a single Redis instance (typically <256GB)?
Do I need Redis Cluster (horizontal sharding)?
You are estimating capacity for a social platform with 200M DAU, where each user makes 5 read requests per day and 0.05 write requests per day. Using a peak multiplier of 3x, what is the approximate peak read QPS, and what does the read-to-write ratio suggest about the architecture?
4. Common System Scale Benchmarks
Use these as sanity checks — if your estimate gives a number wildly outside these ranges, revisit your assumptions:
| System | DAU | QPS (peak) | Storage/year |
|---|---|---|---|
| Twitter-like | 150M | ~100K read QPS | ~200 TB (text) |
| Instagram-like | 500M | ~500K read QPS | ~1.2 PB (photos) |
| YouTube-like | 2B | ~10M read QPS | ~10+ EB (video) |
| WhatsApp-like | 2B | ~100K msg/s | ~500 TB (messages) |
| Uber-like | 100M | ~1M GPS events/s | ~1 TB (ride data) |
| URL Shortener | 100M | ~100K read QPS | ~100 GB (URL mappings) |
Single-Machine Limits (Approximate)
| Resource | Capacity |
|---|---|
| Typical web server (nginx/Node) | 10K–50K HTTP req/s |
| PostgreSQL (OLTP, indexed reads) | 5K–50K QPS |
| PostgreSQL (write-heavy) | 1K–10K writes/s |
| Redis | 100K–500K commands/s |
| Kafka (single broker) | 100K–1M msg/s |
| MySQL (OLTP) | 5K–30K QPS |
| Network bandwidth (1GbE) | ~125 MB/s = ~1 Gbps |
| Network bandwidth (10GbE) | ~1.25 GB/s = ~10 Gbps |
| SSD IOPS | 100K–1M IOPS |
| SSD throughput | 500 MB/s – 7 GB/s (NVMe) |
5. Step-by-Step BOTE Process for Interviews
Phase 1: State Assumptions Out Loud (30 seconds)
"Let me make some assumptions and feel free to correct me:
- 100M daily active users
- Users read 10x more than they write
- Average tweet is 140 bytes (text only, no media for now)"
This shows systematic thinking and gives the interviewer a chance to adjust the problem scope.
Phase 2: Compute QPS (2 minutes)
Step 1: Daily requests
DAU × requests/user/day = 100M × 10 = 1B reads/day
Step 2: Average QPS
1B / 86,400 ≈ 1B / 100K = 10,000 reads/s average
Step 3: Peak QPS
10K × 3 = 30K reads/s (assume 3x peak during busy hours)
Step 4: Write QPS
10% of users write once per day = 10M writes/day
10M / 100K = 100 writes/s average
100 × 5 = 500 writes/s peak
Phase 3: Derive Architecture Decision (30 seconds)
"Read-to-write ratio is 30,000:500 = 60:1. This is heavily read-heavy.
→ I need read caching (Redis) and read replicas
→ The write path is modest — a single primary handles this
→ Let me design accordingly..."
This is the critical step — the math must connect to an architecture choice.
Phase 4: Storage Estimate (1 minute)
Post size: 140 bytes text + 8 bytes post_id + 8 bytes user_id + 8 bytes timestamp
= ~180 bytes per post
Posts per day: 10M
Daily storage: 10M × 180B = 1.8 GB/day
Annual storage: 1.8 GB × 365 ≈ 660 GB/year
5-year storage: ~3.3 TB
"3.3 TB of text fits comfortably in a single database.
No sharding needed for text — but if we add images, the calculus changes..."
Phase 5: Bandwidth (30 seconds, if relevant)
Read response average size: 1 KB (one page of results with 10 posts)
Read bandwidth: 10K req/s × 1 KB = 10 MB/s outbound
→ Well within a single server's bandwidth limit (1 Gbps = 125 MB/s)
→ CDN not strictly required for text (but helpful for latency)
6. Interview Cheat Sheet
5 Sentences to Show Deep Understanding
-
"Before diving into architecture, I want to understand the scale: roughly how many DAU, and what's the read-to-write ratio? The answer fundamentally changes the design — a 10:1 read-heavy system needs aggressive caching; a 1:1 mixed system needs careful write path design."
-
"100K seconds per day is the key constant: to get average QPS from daily requests, divide by 100K. Peak QPS is typically 2–5x average depending on traffic patterns — celebrity systems might see 10x spikes."
-
"The math should drive decisions, not just produce numbers. If peak write QPS is 50K and PostgreSQL handles 10K writes/s on one instance, I need — that's the conclusion I'm looking for."
-
"Storage and QPS estimates tell you different things: QPS drives compute and caching requirements; storage tells you database vs. object storage, thresholds, and backup costs. A system can be low QPS but massive storage (archival), or high QPS but tiny storage (session tokens)."
-
"Order-of-magnitude accuracy is sufficient: if my estimate says 10 TB and the real answer is 7 TB, we make the same architecture decisions. If my estimate says 10 GB and the real answer is 10 TB, we've made completely different decisions — the 10x error matters, the 2x error doesn't."
Common Follow-Up Questions
Q: How do you estimate the number of servers needed? A: (1) Peak QPS ÷ requests_per_server = number of web servers. (2) Add 30–50% headroom for failures and traffic spikes. (3) For databases: if peak QPS exceeds single-instance limit, calculate number of shards. Example: 30K read QPS, each Redis instance handles 300K QPS → 1 Redis instance handles it easily. 30K write QPS, each PostgreSQL handles 10K writes/s → 3 shards minimum, plan for 5.
Q: What's the storage cost implication of your estimates? A: Object storage (S3/GCS) costs ~0.03/GB/month. 1 PB/year ≈ 30K/month in storage costs alone. This drives decisions like: compression (JPEG vs. raw), tiered storage (move old data to Glacier/Coldline at $0.004/GB), and (serve from cache instead of pulling from S3 repeatedly which has egress costs).
Q: How do you account for in your storage estimates? A: Multiply raw storage by factor. PostgreSQL with 3 replicas → 3x storage. Cassandra with RF=3 → 3x storage. Factor this into cost estimates: 3.3 TB of data × 3 replicas = 10 TB total disk usage.
Q: How do you estimate cache hit rate impact on QPS? A: If cache hit rate is 90%: only 10% of reads hit the database. So if peak read QPS is 30K, database sees 3K read QPS — well within single-instance limits. Cache miss creates a burst: if cache is cold or invalidated, all 30K QPS suddenly hit the database (). Add jitter to cache TTLs to stagger expiry.
Common Estimation Mistakes to Avoid
- Forgetting peak multiplier: "150K avg QPS" needs ×2–5 for peak. Design for peak, not average.
- Confusing MB and GB: Powers of 10 errors are catastrophic. Write out units explicitly.
- Not connecting math to decisions: Don't just announce "5 TB/year." Say "5 TB/year means I need object storage, not a relational database, and I should consider tiered storage."
- Forgetting replication: 100 GB of data with 3 replicas is 300 GB of disk.
- Ignoring : Cassandra's SSTable means ~10x . LSM-based systems write more bytes to disk than logical bytes written.
- Assuming uniform traffic: Real traffic has peaks (morning commute, lunch hour, news events). Build in headroom.
Connections to Other Building Blocks
- Sharding & : Your QPS and storage estimates directly determine whether sharding is needed. Rule of thumb: if write QPS > 10K/s on a single node, consider sharding.
- Caching: If read QPS > 50K/s, caching is almost always needed. Cache size = working set × 1.5–2x safety factor.
- : If bandwidth estimates exceed 1–10 Gbps from a single datacenter, or if users are globally distributed, CDN is needed. Especially true for media (video, images).
- Message Queues: If write QPS spikes to >10K/s but average is 1K/s, a (/SQS) buffers the spikes and levels the load to the database.
- Read Replicas: If read QPS is 10–100x write QPS, read replicas distribute the load. Each replica adds a copy of the write rate.
7. Reference: Standard Estimation Scenarios
URL Shortener
Assumptions: 100M URLs created/day, 10B redirects/day
Write QPS: 100M / 100K = 1,000 writes/s
Read QPS: 10B / 100K = 100,000 reads/s (100:1 read-heavy)
URL record size: 6-byte short code + 2048-byte long URL + 8-byte ts = ~2.1 KB
Storage/day: 100M × 2.1 KB = 210 GB/day
5-year storage: 210 GB × 365 × 5 = ~380 TB
Cache: 80% of traffic is top 20% of URLs (Pareto) → 80K most popular URLs × 2.1KB ≈ 170 MB in memory
Conclusion: Heavily read-heavy → Redis cache essential, read replicas needed.
Storage is manageable (few hundred TB) → sharding not immediately required.
Rate Limiter
Assumptions: 1B requests/day, rate limit checked per request
QPS: 1B / 100K = 10,000 QPS average, 50,000 QPS peak
Redis counter check per request: ~0.5ms latency
Memory per counter: 24 bytes (key + counter + TTL)
1M distinct users × 24 bytes = 24 MB per window
Conclusion: Redis easily handles 50K ops/s (capacity: 500K ops/s)
Memory is negligible. Single Redis instance sufficient.
Chat System (WhatsApp-like)
Assumptions: 500M DAU, average 10 messages sent/day, average message 100 bytes
Daily messages: 500M × 10 = 5B messages/day
Message write QPS: 5B / 100K = 50,000 writes/s
Message read QPS: 50K × 10 (read-heavy) = 500K reads/s
Storage/day: 5B × 100 bytes = 500 GB/day
5-year storage: 500 GB × 365 × 5 = ~900 TB
Conclusion: 50K writes/s requires sharding (PostgreSQL: ~10K/s per node → ~5 shards)
Real-time delivery → WebSockets, not HTTP polling
Consider Cassandra (write-optimized) for message storage
A URL shortener system handles 100 million new URLs created per day and 10 billion redirects per day. Which architectural conclusion best follows from this read/write ratio?
Glossary History
Click dotted jargon to save explanations here.
Glossary History
Click dotted jargon to save explanations here.