Skip to content
SparkTime, home
System Design From Zero to Interview-Ready
Lessons
1 · System Design Foundations
2 · APIs and Communication
3 · Capacity Estimation
4 · Core Building Blocks
5 · Databases
6 · Distributed Systems
7 · Reliability and Operations
8 · Architecture and Security
9 · Interview Method and Foundation Case Studies
10 · Real-World Case Studies
11 · Large-Scale Case Studies
12 · Interview Readiness
Lesson 6 of 45

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.

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

#
  1. 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.
  2. 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.
  3. Show the work. Write each step. Wrong numbers with visible reasoning earn more credit than right numbers from nowhere.
  4. 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."
  5. 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:

Code
1 million requests per day  /  86,400 seconds  =  about 12 requests per second

So:

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:

Code
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 headroom

Users, 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:

Code
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 queries

This 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:

Code
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  =  3

In 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.

Java
// 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);    }}
Code
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 second

In 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):

Code
100M x 40 = 4 billion messages/day4 x 10^9 / 86,400 = about 46,000 messages/second on averagePeak: about 92,000 messages/second

Messages delivered (fan-out): a one-to-one message is delivered to 1 recipient; a group message to about 19 others.

Code
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,000

The 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.

Code
Requests in the first minute = 1,000,000 x 5 = 5,000,000Per second = 5,000,000 / 60 = about 83,000 requests per second

That 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:

  1. "Let me assume X DAU, and these actions per user per day." Write them down.
  2. Compute requests per day, then average QPS, then peak QPS, separately for the main read and write operations.
  3. Say the read:write ratio.
  4. Note any fan-out multiplier.
  5. 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:

  1. 250 million requests per day to average QPS.
  2. 5,000 QPS to requests per day.
  3. 2^36 bytes to GB (decimal).
  4. 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
  1. 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).
  2. 5,000 x 86,400 = 432 million requests per day, about 430 million.
  3. 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.
  4. 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:

  1. Registered users used instead of DAU.
  2. Minutes multiplied by a rate per second without converting: 30 minutes is 1,800 seconds.
  3. Bits treated as bytes: 5 Mbps is megabits per second, which is 0.625 MB per second.
  4. No conversion to a rate for bandwidth; a daily total says nothing about the capacity needed at any moment.
  5. Wrong conclusion: video is the textbook case where bandwidth dominates and a CDN is essential.

Redo with 50 million DAU:

Code
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 Tbps

Ten 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

#
  • 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