Back-of-the-envelope math
The point is not the number#
Nobody checks your arithmetic. What the estimate actually does is force every vague word in the prompt to become a number, and it is the numbers that make the rest of the design decidable. "A lot of users" does not tell you whether the data fits on one machine. "4TB a year" does.
The estimate is also how you avoid the most common failure in a system design interview: building an architecture that is wildly over- or under-sized for the problem, and having no way to notice.
So the goal is a handful of numbers, derived out loud, in about three minutes:
- Write QPS and read QPS, at peak
- Storage per day and per year
- Roughly how many machines that implies
Round aggressively, and say that you are#
Use numbers that divide cleanly. The uncertainty in "how many posts does an average user write per day" dwarfs any rounding error you introduce.
| Real value | Use | Why |
|---|---|---|
| 86,400 seconds/day | 100,000 | Division becomes shifting a decimal point |
| 1,024 bytes | 1,000 | Same |
| 2.5 million seconds/month | 2.5 million | Close enough, and easy |
| 31,536,000 seconds/year | 30 million | Same |
A useful anchor: 1 million requests per day is about 12 QPS. Most prompts are within a couple of orders of magnitude of something you can reach from there.
"I'm going to round a day to 100,000 seconds so I can do this in my head — it's about 16% off, which is well inside my error bars on usage." This takes four seconds and pre-empts the only objection.
The standard derivation#
Work in the same order every time so you never lose your place. Take a feed product with 100 million daily active users.
Step 1 — Writes. Assume 2 posts per user per day. That is 200 million writes/day, divided by 100,000 seconds, giving 2,000 writes/second on average.
Step 2 — Reads. Assume each user opens the app 10 times and each open pulls a page of feed. That is 1 billion reads/day, or 10,000 reads/second. The ratio matters more than either number: 5:1 read-heavy here, which immediately tells you caching and read replicas are on the table and that write throughput is not your first problem.
Step 3 — Peak. Traffic is not flat. Most consumer products peak at 2–3× their daily average, and spiky ones far more. At 3×: 6,000 writes/sec and 30,000 reads/sec. Design for this.
Step 4 — Storage. Assume a post is 300 bytes of text plus metadata, call it 1KB with indexes. 200 million × 1KB = 200GB/day, which is ~73TB/year. If 10% of posts carry a 200KB image, that is another 4TB/day — and now the media store dominates the design, not the text.
Step 5 — Machines. If one application server handles 1,000 requests/second, 30,000 peak reads needs about 30 machines, plus headroom for a failure domain — call it 40. If a database node holds 2TB comfortably, 73TB/year means tens of nodes and a sharding conversation within the first year.
Five steps, five numbers, and the architecture has largely chosen itself.
Peak is the number that catches people out#
Designing for the daily average is the single most common estimation error. A system sized for 2,000 writes/second falls over at 6,000, and in production the interesting failures all happen at peak.
Reasonable multipliers to reach for, and to justify:
- 2–3× for a product with steady global usage
- 5–10× for something with a strong daily cycle in one timezone
- 100×+ for event-driven spikes — ticket sales, flash sales, live sports
That last row is not a footnote. A ticketing system is not a system that does 500 QPS and occasionally more; it is a system that does almost nothing and then 50,000 QPS for ninety seconds. Designing for its average produces an architecture that is wrong in every particular. When a prompt has an event shape, the peak is the requirement.
Read/write ratio decides the architecture#
Once you have both numbers, the ratio does a lot of work:
Read-heavy (10:1 or more) — caching is the primary lever, read replicas are cheap, and eventual consistency on the read path is usually acceptable. A URL shortener is the extreme case: written once, read millions of times, so the entire design is about making reads fast and the write path barely matters.
Write-heavy (approaching 1:1 or inverted) — caching does not save you, because you cannot cache a write. The questions become batching, buffering through a queue, and whether writes can be made asynchronous. Metrics ingestion and activity logging live here.
Genuinely balanced — usually the hardest, because neither lever is decisive and you end up trading consistency for throughput explicitly.
State the assumption, do the arithmetic, name the consequence. "100 million DAU, 2 posts each, so 2,000 writes/second average, 6,000 at a 3× peak. Reads are 5× that. That's read-heavy enough that I'll put a cache in front and won't worry about write throughput until much later." Assumption, number, conclusion — every time.
Where this goes wrong#
False precision. "2,314 requests per second" invites an argument about whether it is really 2,314. Say "about 2,000" and move on.
No retention policy. A storage number without a retention window is not an estimate. Ask how long data lives before you multiply by 365.
Forgetting the metadata. Indexes, replication factor and overhead routinely double or triple raw data size. Three replicas of 73TB is 219TB, and that is the number you actually have to buy.
Estimating things nobody asked about. If the prompt is about message delivery, you do not need a storage estimate for profile pictures. Estimate what the design decision depends on.
Next#
You now have request rates. The missing half is where the time inside a single request actually goes — which operations cost microseconds, which cost milliseconds, and how to build a latency budget you can defend. That is the next concept, and it is what turns "this should be fast" into "this is 40ms, and here is where it goes."
Where this shows up
This page is the mechanism on its own. Each problem below bends it to a constraint that page has and this one does not.