Lessons
1 · System Design Foundations
2 · APIs and Communication
3 · Capacity Estimation
4 · Core Building Blocks
5 · Databases
- 12Relational Databases and Data Modeling for System Design
- 13Database Indexes and Query Performance: How to Make Reads Fast
- 14Transactions, Isolation Levels and Concurrency Control: Preventing Race Conditions
- 15Database Replication: Primary-Replica, Read Replicas, Lag and Failover
- 16Database Sharding and Partitioning: How It Works and When You Need It
- 17SQL vs NoSQL: Data Models and How to Choose the Right Database
6 · Distributed Systems
- 18Why Distributed Systems Are Hard: Partial Failure, Timeouts and Clocks
- 19CAP Theorem and Consistency Models Explained Without the Myths
- 20Idempotency, Retries and Message Delivery Guarantees
- 21Distributed Transactions: Two-Phase Commit, the Outbox Pattern and Sagas
- 22Distributed Locks, Leases, Leader Election and Consensus
7 · Reliability and Operations
8 · Architecture and Security
9 · Interview Method and Foundation Case Studies
10 · Real-World Case Studies
- 33Design a Notification System: Email, SMS and Push at Scale
- 34Design a Chat System Like a Messaging App
- 35Design a News Feed: Fan-Out, Ranking and the Celebrity Problem
- 36Design Search Autocomplete (Typeahead)
- 37Design a Distributed Job Scheduler
- 38Design a Ticket Booking System Without Overselling
- 39Design a Payment System: Idempotency, Ledgers and Reconciliation
11 · Large-Scale Case Studies
- 40Design a Video Streaming Platform: Upload, Transcoding and Adaptive Streaming
- 41Design a Ride-Hailing System: Location, Matching and Real-Time Updates
- 42Design a Food Delivery Platform: Orders, Restaurants and Delivery Partners
- 43Design an E-Commerce System: Catalog, Cart, Checkout, Inventory and Flash Sales
- 44Design a Web Search Engine: Crawling, Inverted Indexes and Ranking
12 · Interview Readiness
Lesson 6 · Capacity Estimation
Back-of-the-Envelope Estimation: From Users to Peak QPS
Capacity estimation from absolute basics: units and powers of two, seconds in a day, and the funnel from total users to MAU, DAU, requests per day, average QPS and peak QPS. Includes peak factors you can derive, read and write splits, fan-out, three worked examples and a small calculator.
For
Beginners who find estimation intimidating, and interview candidates who want a reliable, repeatable way to turn user numbers into requests per second.
Level
Before you start
Read Functional and Non-Functional Requirements (article 02). You need multiplication, division and powers of ten; nothing more. Article 05 helps with the idea of background work.
On this page
Key takeaways
- Estimation exists to find out which parts of a design are hard, not to be precise; round aggressively and state every assumption.
- Remember that a day has about 86,400 seconds, so 1 million requests a day is about 12 per second.
- Work down the funnel: users, DAU, actions per user, requests per day, average QPS, then peak QPS.
- Derive the peak factor from when traffic happens instead of guessing; plan for events that exceed it.
- Estimate reads and writes separately, and account for fan-out, where one user action becomes many requests.
"How many servers do we need?" is a question most beginners answer with a guess, and most experienced engineers answer with a calculation they can do on the back of an envelope in two minutes. The calculation does not need to be accurate to the nearest server. It needs to tell you whether you need one database or fifty, whether a cache is essential or optional, whether a single machine can handle the writes.
That is what back-of-the-envelope estimation is: quick, rough arithmetic, with stated assumptions, that tells you where the hard parts of a design are. This article and the next teach it from absolute zero. This one covers traffic: from a number of users to queries per second (QPS). Article 07 covers storage, bandwidth, cache size and server count.
What you will learn
#- Why estimates exist and how precise they need to be.
- Data units (KB, MB, GB, TB, PB), powers of two, and the difference between bits and bytes.
- Time conversions you should know by heart.
- The traffic funnel: total users, MAU, DAU, actions, requests per day, average QPS, peak QPS.
- How to derive a peak factor, and why special events break it.
- Read and write ratios, and fan-out from one action to many requests.
- Three complete worked examples, and a small calculator in Java.
Why estimate at all?
#Estimates answer design questions:
- Is this read-heavy or write-heavy? That decides whether caches and replicas help.
- Can one database handle the writes? If yes, you avoid sharding, one of the most complex things you can add.
- Does the data fit on one machine? If not, you must partition it.
- Is bandwidth the bottleneck? For video, it usually is, which is why CDNs matter.
- How big must the cache be? Can it fit in memory on a few nodes?
An estimate that is off by 30% almost never changes these answers. An estimate that is off by 100 times always does. So the goal is to get the order of magnitude right: is it 10, 1,000 or 100,000 per second?
Ground rules
#- State assumptions out loud. "Assume 10 million daily active users, each viewing the feed 10 times a day." The interviewer can then correct an assumption instead of your arithmetic.
- Round aggressively. 86,400 can be 100,000 when you only need an order of magnitude; 2.7 can be 3. Keep one or two significant figures.
- Show the work. Write each step. Wrong numbers with visible reasoning earn more credit than right numbers from nowhere.
- Sanity-check the result. "That is 3,000 writes per second; a single well-tuned relational database can often handle that order of writes, but I would confirm with a load test."
- Only estimate what drives a decision. You do not need ten numbers. You need the two or three that decide the design.
Units: bytes, bits and powers of two
#Data sizes
#Unit | Decimal value (used for estimates) | Power of 2 it approximates | Exact binary value |
|---|---|---|---|
1 KB (kilobyte) | 10^3 = 1,000 bytes | 2^10 | 1,024 bytes (a KiB) |
1 MB (megabyte) | 10^6 bytes | 2^20 | 1,048,576 bytes (a MiB) |
1 GB (gigabyte) | 10^9 bytes | 2^30 | about 1.07 x 10^9 (a GiB) |
1 TB (terabyte) | 10^12 bytes | 2^40 | about 1.10 x 10^12 (a TiB) |
1 PB (petabyte) | 10^15 bytes | 2^50 | about 1.13 x 10^15 (a PiB) |
Storage vendors use decimal units; operating systems often show binary units. The difference is 2.4% at KB and grows to about 10% at TB. For estimation, use decimal units and ignore the difference, unless an interviewer asks.
Remembering that 2^10 is about 1,000 lets you move between the two worlds quickly. For example, 2^32 (the number of values a 32-bit integer can hold) is 2^2 x 2^30, about 4 x 10^9, or 4 billion. That fact matters when you choose id sizes: a 32-bit id runs out after about 4 billion rows.
Bits versus bytes
#Network speeds are quoted in bits per second (Mbps, Gbps); storage in bytes. One byte is 8 bits.
- A 1 Gbps network link moves at most about 1,000,000,000 / 8 = 125 MB per second.
- A 5 Mbps video stream uses 5 / 8 = about 0.6 MB per second, or about 37.5 MB per minute (5 Mbps x 60 seconds = 300 megabits = 37.5 MB).
Mixing bits and bytes is one of the most common estimation errors, and it is off by a factor of 8.
Typical sizes (assumptions to adapt)
#These are reasonable starting assumptions, not facts about any particular system. Adjust them to the problem and say so.
Thing | Assumed size |
|---|---|
Numeric id (64-bit) or timestamp | 8 bytes |
UUID | 16 bytes in binary; 36 characters as text |
A short text post with its metadata | 1 KB |
A typical JSON API response | 1 to 10 KB |
A compressed photo from a phone | 1 to 3 MB |
A thumbnail | 10 to 50 KB |
One minute of video at 5 Mbps | 37.5 MB (computed above) |
Time: the numbers to know by heart
#Period | Seconds | Shortcut |
|---|---|---|
1 minute | 60 | |
1 hour | 3,600 | |
1 day | 86,400 | about 10^5 for rough work |
1 month (30 days) | about 2.6 million | about 2.5 x 10^6 |
1 year | about 31.5 million | about 3 x 10^7 |
The single most useful conversion in this course:
1 million requests per day / 86,400 seconds = about 12 requests per secondSo:
Per day | Per second (average) |
|---|---|
1 million | about 12 |
10 million | about 120 |
100 million | about 1,200 |
1 billion | about 12,000 |
If you use 100,000 seconds per day instead of 86,400, your QPS comes out about 14% low. That is fine for orders of magnitude, but if you are close to a limit, use the exact figure.
The traffic funnel
#Every traffic estimate walks down the same funnel:
Total registered users | x fraction active in a month vMAU (monthly active users) | x fraction active on a given day vDAU (daily active users) | x actions per user per day vActions per day | x requests per action (fan-out) vRequests per day | / 86,400 vAverage QPS | x peak factor vPeak QPS <-- design for this, plus headroomUsers, MAU and DAU
#- Registered users is the biggest number and the least useful. Many accounts are dormant.
- MAU (monthly active users) counts distinct users active at least once in a month.
- DAU (daily active users) counts distinct users active on a given day. This is the number that drives daily load.
The ratio DAU / MAU tells you how habitual the product is. A messaging app people open every day has a high ratio; a tax-filing app has a very low one. If the interviewer gives you only registered users, assume a ratio and say so: "Assume 50 million registered, 20 million MAU, 10 million DAU."
Actions per user and requests per action
#An action is something a user does: open the feed, like a photo, send a message. One action often causes several requests: opening the home screen might call the feed endpoint, the notifications count and the profile summary. And one request may cause several database queries or calls to other services.
Keep the levels separate and multiply through only where it matters:
1 "open home screen" action = 3 API requests (feed, notification count, profile summary) = for the feed request: 1 cache lookup + on a miss, 2 database queriesThis multiplication is called fan-out, and forgetting it is a classic way to underestimate load on an inner component by 10 times.
Average to peak
#Traffic is not flat. Consumer apps in one region are quiet at 4 a.m. and busy in the evening. You must design for the peak, not the average, or the system falls over every evening.
You can derive a peak factor instead of guessing. Suppose half of a day's traffic arrives during four evening hours:
Average rate = daily requests / 24 hoursPeak rate = (0.5 x daily requests) / 4 hoursPeak / average = (0.5 / 4) / (1 / 24) = 0.5 x 24 / 4 = 3In general, if a fraction f of daily traffic happens in h hours, the peak factor is f x 24 / h. A factor of 2 to 3 is a common assumption for a regional consumer app. A global app with users in every time zone has a flatter curve and a lower factor. A workplace tool has a sharp 9-to-6 shape.
Special events break the average
#Some peaks are not daily cycles at all: a big sale, a cricket final, results day, New Year's midnight messages, a viral post. These can exceed the normal peak by an order of magnitude for minutes or hours. If the requirements mention such events, estimate them separately (worked example 3) and design for them explicitly: pre-scaling, queues to absorb bursts, and graceful degradation (article 23).
Headroom
#Even the peak is not the number you provision for. Add headroom for:
- growth until the next capacity review;
- losing part of the fleet (a server or a whole availability zone) during the peak;
- estimation error.
A common planning habit is to keep peak utilisation well below 100%, for example aiming for 50 to 70%, and to make sure the system can carry the peak with one zone lost. Article 07 does this arithmetic for servers.
Reads, writes and the ratio between them
#Estimate reads and writes separately, because they scale differently:
- Reads can be served by caches, CDNs and read replicas. Adding copies adds read capacity.
- Writes must reach the authoritative copy of the data. Copies do not help; you need a bigger machine, fewer writes (batching) or partitioning.
The read:write ratio is one of the first things to state. Social feeds, product catalogues and URL shorteners are heavily read-dominant (often 100:1 or more). Logging, metrics and location tracking are write-dominant. A chat app is somewhere in between.
Worked example 1: Pixly
#Assumptions (stated, round, adjustable):
- 50 million registered users, 10 million DAU.
- Each active user opens the feed 10 times a day.
- Each active user likes 5 photos a day.
- One in five active users uploads one photo a day (0.2 uploads per user per day).
- Peak factor 3 (half the traffic in 4 evening hours).
Operation | Per day | Average QPS | Peak QPS (x3) |
|---|---|---|---|
Feed reads | 10M x 10 = 100M | 100M / 86,400 = about 1,160 | about 3,500 |
Likes (writes) | 10M x 5 = 50M | about 580 | about 1,700 |
Uploads (writes) | 10M x 0.2 = 2M | about 23 | about 70 |
What the numbers tell us:
- Feed reads dominate. About 3,500 per second at peak, each needing data from many followed users. This is where caching and precomputation matter (article 35).
- Likes are a surprisingly large write load. 1,700 writes per second at peak, all small. They are good candidates for batching or counting asynchronously.
- Uploads are few (70 per second at peak) but each is large. Their challenge is storage and bandwidth, not request rate, which is article 07's subject.
Notice that a single number like "10 million DAU" says almost nothing on its own. Broken down by operation, it tells you exactly where to spend design effort.
The same numbers from a small calculator
#This Java program reproduces the table. It is deliberately simple; the point is the arithmetic, which you can equally do on paper or in a spreadsheet.
// File: TrafficEstimate.javaimport java.util.Locale;public class TrafficEstimate { static final double SECONDS_PER_DAY = 86_400; static void line(String name, double dau, double perUserPerDay, double peakFactor) { double perDay = dau * perUserPerDay; double avgQps = perDay / SECONDS_PER_DAY; double peakQps = avgQps * peakFactor; System.out.printf(Locale.US, "%-11s %,13.0f/day avg %,6.0f QPS peak %,6.0f QPS%n", name, perDay, avgQps, peakQps); } public static void main(String[] args) { double dau = 10_000_000; double peakFactor = 0.5 * 24 / 4; // half the traffic in 4 hours System.out.printf(Locale.US, "Peak factor: %.1f%n", peakFactor); line("Feed reads", dau, 10, peakFactor); line("Likes", dau, 5, peakFactor); line("Uploads", dau, 0.2, peakFactor); System.out.printf(Locale.US, "1 million per day = %.1f per second%n", 1_000_000 / SECONDS_PER_DAY); }}Peak factor: 3.0Feed reads 100,000,000/day avg 1,157 QPS peak 3,472 QPSLikes 50,000,000/day avg 579 QPS peak 1,736 QPSUploads 2,000,000/day avg 23 QPS peak 69 QPS1 million per day = 11.6 per secondIn an interview you would say "about 1,200 average, 3,500 peak" rather than 1,157 and 3,472. The extra digits add nothing.
Worked example 2: a messaging app
#Assumptions:
- 100 million DAU.
- Each sends 40 messages a day.
- 80% of messages are one-to-one; 20% go to groups with an average of 20 members.
- Peak factor 2 (usage is spread through the day, with an evening rise).
Messages sent (writes):
100M x 40 = 4 billion messages/day4 x 10^9 / 86,400 = about 46,000 messages/second on averagePeak: about 92,000 messages/secondMessages delivered (fan-out): a one-to-one message is delivered to 1 recipient; a group message to about 19 others.
Deliveries per message = 0.8 x 1 + 0.2 x 19 = 0.8 + 3.8 = 4.6Deliveries per second at peak = 92,000 x 4.6 = about 420,000The fan-out multiplies the delivery work by almost five. A design that sized the delivery system for 92,000 per second would be undersized by a factor of 4.6. This is why chat and feed designs pay close attention to group sizes (articles 34 and 35).
Worked example 3: a flash sale
#An online store normally handles 2 million product-page views a day: 2,000,000 / 86,400 = about 23 per second, about 70 per second at an ordinary peak.
It announces a sale of a popular phone at 12:00 noon. Marketing expects 1 million people to be waiting, and assume each refreshes or clicks about 5 times in the first minute.
Requests in the first minute = 1,000,000 x 5 = 5,000,000Per second = 5,000,000 / 60 = about 83,000 requests per secondThat is more than 1,000 times the ordinary peak, concentrated in one minute, and it lands on the single most contended data in the system: the stock count of one product. Normal autoscaling cannot add capacity fast enough to react to a spike that arrives in seconds. The design responses (serving the product page from a CDN, a virtual waiting room, queueing purchase attempts, atomic stock decrements) are the subject of article 43. The estimate is what tells you the problem exists.
Sanity checks and common traps
#After every estimate, ask:
- Does the magnitude make sense? If a hobby app needs 50,000 QPS, re-check the assumptions.
- Did I use DAU, not registered users?
- Did I separate reads from writes?
- Did I include fan-out to inner components?
- Did I use the peak, not the average, for capacity?
- Bits or bytes?
- Per day, per hour or per second? Write the unit next to every number.
Trade-offs in estimation
#Choice | Trade-off |
|---|---|
Round numbers (100,000 seconds per day) versus exact (86,400) | Speed and clarity versus about 14% accuracy; use exact numbers near a limit |
Generous versus tight assumptions | Over-provisioning wastes money; under-provisioning fails at peak; state both and choose |
Designing for the normal peak versus the event peak | Cheaper everyday capacity versus surviving rare spikes; often solved with queues and degradation instead of raw capacity |
More estimates versus fewer | Completeness versus interview time; estimate only what changes a decision |
Failure modes of a bad estimate
#- Underestimate: the system fails at the first busy evening or sale; databases saturate; latency climbs; Little's Law (article 02) turns the slowness into overload.
- Overestimate: you build sharding, multi-region replication and a fleet of caches for a load one server could handle. Cost and complexity grow, and complexity itself causes failures.
- Right average, wrong peak: everything looks fine in the daily dashboard while users suffer for two hours every evening.
Common mistakes
#- Starting with servers instead of starting with users and actions.
- Treating registered users as daily users.
- Using the average as the design load.
- Forgetting fan-out, so inner services are sized for the wrong load.
- Too many digits, which wastes time and suggests false precision.
- Not stating assumptions, so the interviewer cannot help you.
- Skipping the "so what": every number should lead to a design conclusion.
In an interview
#Spend about five minutes. A clean script:
- "Let me assume X DAU, and these actions per user per day." Write them down.
- Compute requests per day, then average QPS, then peak QPS, separately for the main read and write operations.
- Say the read:write ratio.
- Note any fan-out multiplier.
- State the conclusion: "Reads at 3,500 per second at peak suggests a cache; writes at 70 per second are easily handled by one primary database."
Then move on. Storage and bandwidth follow in the same style (article 07).
Exercises
#Exercise 1
Quick conversions
#Convert, rounding sensibly:
- 250 million requests per day to average QPS.
- 5,000 QPS to requests per day.
- 2^36 bytes to GB (decimal).
- A 100 Mbps link to MB per second.
Exercise 2: Derive the peak
#A food-delivery app in one country receives 40% of its daily orders between 19:00 and 22:00, and 25% between 12:00 and 14:00. What are the peak factors for the dinner and lunch windows? Which do you design for?
Exercise 3: Estimate a news app
#A news app has 30 million registered users, a DAU/MAU ratio of 0.4, and MAU of 15 million. Each DAU opens 8 articles a day; each article page makes 3 API requests (article body, related articles, comments count). Editors publish 2,000 articles a day. Assume a peak factor of 2.5.
Compute DAU, article reads per day, API requests per second (average and peak), and the read:write ratio of articles. What design conclusion follows?
Exercise 4: Find the errors
#A candidate estimates a video app: "We have 200 million users. Each watches 30 minutes a day at 5 Mbps. That is 200M x 30 x 5 = 30,000 MB per day, so bandwidth is small and we don't need a CDN." List every error and redo the bandwidth estimate (assume 50 million DAU).
Show solutionHide solution
- 250,000,000 / 86,400 = about 2,900 QPS (or about 2,500 if you use 100,000 seconds per day; either is acceptable for an order of magnitude).
- 5,000 x 86,400 = 432 million requests per day, about 430 million.
- 2^36 = 2^6 x 2^30 = 64 x 2^30, about 64 x 1.07 x 10^9 = about 69 GB (68.7 GB exactly). Using 2^30 as 10^9 gives 64 GB, which is fine for rough work.
- 100 Mbps / 8 = 12.5 MB per second.
Exercise 2
Show solutionHide solution
Peak factor = f x 24 / h.
- Dinner: 0.40 x 24 / 3 = 3.2.
- Lunch: 0.25 x 24 / 2 = 3.0.
Design for the higher one, dinner at 3.2 times the average, plus headroom. The lunch peak is nearly as high, which is useful to know: there is no quiet afternoon to rely on for heavy batch jobs between 12:00 and 22:00.
Also check whether particular days (weekends, festivals, big cricket matches) are higher than an average day; if so, the "average day" itself should be the busy day.
Exercise 3
Show solutionHide solution
- DAU = 0.4 x 15M = 6 million. (Registered users do not enter the calculation once MAU is known.)
- Article reads per day = 6M x 8 = 48 million.
- API requests per day = 48M x 3 = 144 million. Average QPS = 144M / 86,400 = about 1,700. Peak = 1,700 x 2.5 = about 4,200.
- Article writes: 2,000 per day. Read:write ratio of articles = 48,000,000 / 2,000 = 24,000 to 1.
Conclusion: the system is extremely read-heavy, and the same few thousand articles are read by millions. Article bodies are ideal for caching and for serving through a CDN; one modest database easily handles 2,000 article writes a day. The comments count, which changes often, might be cached for a few seconds and updated asynchronously.
Exercise 4
Show solutionHide solution
Errors:
- Registered users used instead of DAU.
- Minutes multiplied by a rate per second without converting: 30 minutes is 1,800 seconds.
- Bits treated as bytes: 5 Mbps is megabits per second, which is 0.625 MB per second.
- No conversion to a rate for bandwidth; a daily total says nothing about the capacity needed at any moment.
- Wrong conclusion: video is the textbook case where bandwidth dominates and a CDN is essential.
Redo with 50 million DAU:
Data per user per day = 1,800 s x 0.625 MB/s = 1,125 MB, about 1.1 GBData per day = 50M x 1.1 GB = 55 million GB = 55 PB per dayAverage egress = 55 x 10^15 bytes / 86,400 s = about 640 GB/s, about 5 TbpsPeak (factor 2) = about 10 TbpsTen terabits per second is far beyond what any single data centre should serve directly to the internet. A CDN that caches popular videos near viewers is not optional; it is the main part of the design (article 40).
Where to go next
#- Next: Estimating Storage, Bandwidth, Cache Size and Server Count turns these request rates into bytes, links, memory and machines.
- Practice: every case study from article 30 onwards starts with an estimate in this style. Try each one yourself before reading the solution.
- Technology
- Software Engineering
- #beginners
- #capacity estimation
- #distributed systems
- #roadmap
- #scalability
- #system design
- #system design interview
Connected lessons
Linked from 3 guides
Other pages in the library that point here.
Keep reading
More in Technology →Guide · Technology
How to Learn Programming When AI Can Already Write Code
Guide · Technology
Start Here: Your Roadmap from Zero to Job-Ready DSA
Guide · Career
A LinkedIn Profile That Gets Recruiter Messages

