Back-of-the-Envelope Estimation
Turn 'a lot of users' into QPS, storage, and bandwidth in your head. The math that sizes a design in two minutes.
System design gets vague until you put numbers on it. “A lot of traffic” is not a requirement; 12k reads/sec at peak is. Back-of-the-envelope estimation is the skill of turning product language into rough QPS, storage, bandwidth, and machine counts before you draw the architecture.
The goal is not precision. The goal is to get within an order of magnitude fast enough that your design choices are grounded: cache or no cache, queue or no queue, one database node or a sharded fleet.
The mental model
Every estimate is a unit conversion. Start with users, actions, and object sizes; convert them into rates; then add a peak factor and replication/headroom. Keep the numbers round so you can reason out loud without a calculator.
SECONDS_PER_DAY = 86_400 # use 100_000 in your head
avg_qps = daily_events / SECONDS_PER_DAY
peak_qps = avg_qps * peak_factor
storage_per_day = events_per_day * bytes_per_event
bandwidth_per_sec = daily_bytes_served / SECONDS_PER_DAY
A good interview estimate sounds like this: “10 million users, 20 actions per user per day, so 200 million actions/day. Divide by roughly 100k seconds/day: about 2k QPS average. With a 5x peak, design for 10k QPS.”
Latency numbers worth carrying around
These are approximate, but the ratios matter more than the exact values.
| Operation | Rough latency | What it means |
|---|---|---|
| CPU cache / register work | ~1 ns | Essentially free at system-design scale |
| Main memory lookup | ~100 ns | In-memory caches are extremely fast |
| SSD random read | ~100 µs | About 1,000x slower than memory |
| Same-datacenter network round trip | ~0.5-1 ms | Fast, but not free in fan-out paths |
| Disk seek on spinning disk | ~10 ms | Avoid random seeks on old storage paths |
| Cross-region round trip | ~50-150 ms | Dominates user-visible latency |
| Human-noticeable delay | ~100 ms | Above this, interactions start to feel slower |
The headline: memory beats SSD, local networks beat cross-region networks, and one slow remote dependency can dominate an otherwise fast request.
Storage powers of ten and two
For estimation, decimal units are fine:
| Unit | Rule of thumb |
|---|---|
| 1 KB | one small JSON object or paragraph |
| 1 MB | a medium image or a few hundred pages of text |
| 1 GB | about a thousand MB |
| 1 TB | about a thousand GB |
| 1 PB | about a thousand TB |
Binary units (1 KiB = 1024 bytes) matter in low-level code. In design rounds, 1 GB ~= 1 billion bytes is close enough. The bigger mistake is forgetting multipliers: replicas, indexes, thumbnails, compression, retention, and backups.
DAU to QPS
Traffic estimates usually start from daily active users. The conversion is:
- Estimate actions per active user per day.
- Multiply by DAU to get daily events.
- Divide by about 100k seconds/day to get average QPS.
- Multiply by a peak factor, often 3x-10x depending on the product.
| Product shape | Peak factor |
|---|---|
| Enterprise dashboard, business hours | 3x-5x |
| Consumer social app | 5x-10x |
| Live sports, ticket drops, breaking news | 20x or more |
| Batch ingestion with scheduled jobs | Depends on the schedule, not DAU |
Peak is where systems fail. Average QPS is the number you use to sanity-check the business; peak QPS is the number you use to size the online path.
Storage and bandwidth
Storage is a rate times retention:
stored_bytes = writes_per_day * bytes_per_write * retention_days
physical_bytes = stored_bytes * replication_factor
Bandwidth is bytes served over time. Separate ingress from egress because uploads and downloads often have different sizes, paths, and costs. Then ask what can be served from a CDN; origin bandwidth is the expensive part.
| Estimate | Include these multipliers |
|---|---|
| Database storage | row size, indexes, replication, backups, retention |
| Object storage | original files, derived files, metadata, replication |
| Cache memory | key size, value size, allocator overhead, replicas, headroom |
| Network bandwidth | request/response bytes, peak factor, CDN hit rate |
Pattern recognition
Variations
Worked problems
Use round numbers. The point is not to impress with arithmetic; it is to expose the design pressure.
Size a photo-sharing app
A photo-sharing app has 10 million DAU. Each active user uploads 2 photos/day and views 20 photos/day. Originals average 5 MB. Each photo also produces three thumbnails totaling 600 KB. Estimate peak upload QPS, read QPS, storage growth, and egress bandwidth.
Approach. Convert daily actions to average QPS with events/day ÷ 100k, then apply a peak factor. For storage, include originals and derived thumbnails. For bandwidth, reads dominate and should be served through a CDN.
Show solution
Daily uploads:
10M users × 2 uploads/user/day = 20M uploads/day
20M / 100k seconds ~= 200 uploads/sec average
With a 5x peak: design for ~1,000 uploads/secDaily reads:
10M users × 20 views/user/day = 200M photo views/day
200M / 100k seconds ~= 2,000 reads/sec average
With a 5x peak: design for ~10,000 reads/secStorage growth per day:
| Item | Math | Result |
|---|---|---|
| Originals | 20M × 5 MB | 100 TB/day |
| Thumbnails | 20M × 0.6 MB | 12 TB/day |
| Metadata | 20M × ~1 KB | ~20 GB/day |
Call it 112 TB/day logical before replication. With object-store replication or erasure coding, budget roughly 150-300 TB/day physical depending on durability settings.
Bandwidth: if a viewed image averages 300 KB after CDN resizing, 200M × 300 KB is about 60 TB/day. Divide by 100k seconds: about 600 MB/sec average, then 3 GB/sec at a 5x peak. That pushes you toward CDN-first delivery, not origin serving.
Estimate cache memory for a working set
An ecommerce catalog has 50 million products. The API returns a 2 KB JSON blob per product. Traffic is highly skewed: the hottest 10% of products receive 90% of reads. Estimate the Redis memory needed to cache the hot set with replicas and headroom.
Approach. Do not cache the whole catalog unless the math says it is cheap. Estimate hot keys × value size, then add overhead, replication, and headroom.
Show solution
The hot set is 10% × 50M = 5M products.
Raw values:
5M products × 2 KB = 10 GBRedis is not just raw values. Keys, metadata, allocator overhead, and fragmentation can easily double the footprint. So a practical per-copy estimate is:
10 GB raw × 2 overhead = 20 GB per cache copyIf you run three replicas or shards with redundancy, budget about 60 GB. Add 30% headroom so eviction does not start during normal growth: 80 GB is the right order of magnitude.
This estimate also tells you the design is reasonable. Caching all 50M products would be about 800 GB after the same multipliers; caching the hot set is a much smaller operational problem.
Average traffic hides the launch spike
A news app averages only 500 article requests/sec. During a breaking-news push, 4 million users open the same story over 5 minutes, and each page load triggers three API calls. What capacity should the online path expect, and what changes keep the origin from falling over?
Approach. Ignore the daily average and model the event window directly. Then separate cacheable work from personalized work.
Show solution
The spike is:
4M users × 3 API calls = 12M API calls
5 minutes = 300 seconds
12M / 300 ~= 40,000 API calls/secThat is 80x the normal 500 rps average. Designing from the average would under-provision the system by two orders of magnitude.
A reasonable response:
client
-> CDN caches article HTML/JSON and images
-> API gateway rate limits abusive clients
-> stateless app tier handles personalized calls
-> queue records analytics asynchronously
-> database sees only cache misses and user-specific readsThe article content should be pre-warmed in the CDN as the push goes out. View counts and analytics should go to a queue or streaming log; they do not belong on the synchronous path. Personalized state can degrade gracefully: show the article first, load comments or recommendations later.