System Design · Module 4 · Lesson 1 of 4 · 35 min
From Active Users to Average and Peak QPS
Convert user activity into separate read and write rates, model bursts, and explain which assumptions control the answer.
Calculate the database workload →01 The idea
The problem this lesson solves
“We have 100,000 users” does not tell you how many servers to run. Users generate actions, actions generate requests, and requests generate downstream work. Capacity estimation follows that chain with explicit units. The aim is to find the assumptions that affect the design, not to produce a large impressive number or predict hardware performance without measurements.
You need multiplication, division and unit conversion. Keep reads, writes and bytes in separate calculations.
02 Worked example
Convert daily usage into peak traffic
03 The method
Understand the mechanism
Translate people into operations
Daily active users, or DAU, counts distinct users active in a day under the product’s definition. It is not the number online at the same instant and not the number of registered accounts. To estimate work, multiply active users by actions per active user.
Assume 100,000 daily active users each follow ten short links per day. That produces 1,000,000 redirect operations/day. If each operation makes one request to this service, it also produces 1,000,000 incoming redirect requests/day before retries. Make that one-request assumption visible.
One user action can produce several calls. A page might fetch metadata, permissions and analytics separately. Conversely, a browser or edge cache might satisfy a request before it reaches the application. Draw the workload boundary so you know whether you are estimating user actions, gateway requests or database queries.
Keep writes separate. Assume 10,000 new links/day. Do not infer this number from redirects unless the product model actually relates them. Read-heavy and write-heavy paths can require different capacity and correctness mechanisms even when their total request counts look similar.
Convert daily counts into average rates
One day contains 24×60×60 = 86,400 seconds. Average redirect QPS is 1,000,000/86,400 ≈ 11.57 requests/s. Average creation QPS is 10,000/86,400 ≈ 0.1157 writes/s. The units cancel correctly: requests/day divided by seconds/day gives requests/second.
This arithmetic is a sanity check. If someone claims a million daily requests means a million QPS, multiplying back by 86,400 reveals the error. If an estimate appears implausibly small, check whether the input was daily users or simultaneously active users.
The average is useful for total work and rough sustained resource use. It is not a peak provisioning target. A service used mainly during a few local hours can have a much higher daytime rate than its full-day average.
Avoid rounding too early. Keep a few meaningful digits while deriving the result, then communicate an appropriate approximation. Saying roughly 12 average QPS is reasonable; presenting 11.574074 as measured production truth is not.
Model peaks, bursts and geographic concentration
Assume a peak factor of five for this exercise. Peak reads are 11.57×5 ≈ 57.87 QPS, and peak creations are 0.1157×5 ≈ 0.579 QPS. This factor is an assumption about the relationship between average and peak, not a property of all internet services.
Different operations may peak at different times. A campaign can create links before users begin clicking them. A deployment can cause synchronized refreshes. A batch importer can create a write spike unrelated to DAU. Use separate peak factors when the workloads differ.
Also name the interval over which peak is measured. Fifty requests spread evenly over a second is different from fifty arriving in one millisecond and then no more for the rest of the second. Queues and concurrency respond to the arrival pattern, not only the average rate over a convenient bucket.
Geographic totals can hide regional imbalance. If 80% of traffic reaches one region, dividing the global rate equally across four regions underestimates the busiest one. Failover can concentrate traffic further when a region is removed.
Convert incoming requests into dependency demand
If every redirect performs one database lookup, peak origin reads are initially 57.87/s. At a 90% cache hit ratio, the miss fraction is 0.10, so modeled database reads become 57.87×0.10 ≈ 5.79/s. Creation writes remain separate.
This model assumes one origin read per miss and no additional database work. If a miss checks permissions in another table or writes an analytics event, add those operations. If retries repeat failed lookups, include retry amplification. A cache hit ratio is not a universal multiplier for all database activity.
Now model a cold cache. At 0% hits, database reads return to 57.87/s, about ten times the warm-cache origin rate. A design sized only for 5.79/s can fail during restart or invalidation even though external traffic has not increased.
Hot keys complicate averages. A single viral code may produce most of the hits while many unique codes miss. The origin cost per miss may also vary. Track request mix and miss-path cost rather than treating every request as identical.
Turn uncertainty into scenarios
Create baseline, high-traffic and recovery scenarios. Baseline uses the assumed active users and peak factor. High traffic might double actions per user. Recovery keeps traffic fixed but sets cache hits to zero or removes an app instance.
Compare which change has the largest effect on the constrained resource. Doubling external traffic doubles simple origin demand; changing hit ratio from 99% to 90% increases the miss fraction tenfold. That can be more consequential than a modest user-growth forecast.
Use sensitivity analysis to choose measurements. If server count changes dramatically with per-request CPU time, benchmark that path. If storage is dominated by unknown payload size, sample actual records. Refining an input that does not affect the decision wastes time.
Keep exercise assumptions distinct from capacity evidence. A formula can estimate offered work. It cannot tell you that one server safely processes 100 QPS unless that budget comes from a relevant test at the required latency and error target.
Explain what the estimate changes
At roughly 58 peak redirects/s and under one creation/s, these inputs alone do not justify a distributed sharded database. Start by testing a simpler design, including its failure behavior. Small QPS does not imply that correctness or availability can be ignored.
If the service later reaches a much higher read load, use the measured bottleneck to decide among query optimization, caching, read replicas or app scaling. If writes or data volume become the limit, the relevant choices differ. The estimate helps locate the question; it does not answer every architecture question automatically.
Present the final worksheet with input, formula, result and interpretation. “57.87 peak redirect QPS before cache” is more useful than “QPS=58” because the boundary remains visible. Include the cold-cache result alongside the warm one.
Finish with a verification plan: measure active-user behavior, peak distribution, retry rate and origin work per request. A good estimate becomes the first version of a measurable capacity model rather than a number abandoned after the interview.
Guided tutorial
Build the traffic worksheet
Write 100,000 DAU × 10 redirects/user/day = 1,000,000 redirects/day. Divide by 86,400 and multiply by five. Keep requests/s on the result. Separately calculate the creation path from 10,000/day rather than adding it to the reads too early.
Calculate dependency work
Apply a 90% hit ratio to reads only. Record about 5.79 origin reads/s and 0.579 peak creation writes/s as different rows. Add a hypothetical analytics write per redirect and observe that this new feature would create about 57.87 peak analytics writes/s.
Stress the cache assumption
Change the hit ratio to zero without changing DAU or the peak factor. Origin reads become 57.87/s. Run both console presets and compare the origin-read statistic. Explain why recovery load can be much larger than normal dependency load.
State a decision and a measurement
Write that the current estimate supports benchmarking a simple relational design before introducing shards. Then identify the unknown most likely to change that decision: query cost, availability requirement, traffic concentration or record growth. Specify the measurement that would replace your assumption.
Python arithmetic
daily_reads = 100000 * 10
average_read_qps = daily_reads / 86400
peak_read_qps = average_read_qps * 5
average_write_qps = 10000 / 86400
peak_write_qps = average_write_qps * 5
# Console also shows database reads after cache hits.Check your result
Average reads are about 11.57/s and peak reads about 57.87/s. With 90% cache hits, origin reads are about 5.79/s; at 0% hits they return to 57.87/s.
Recompute traffic and cache scenarios
All inputs are exercise assumptions. Change one at a time and watch how incoming demand and origin demand differ.
daily_reads = 100000 * 10
average = daily_reads / 86400
peak = average * 5
print(f"average_reads_per_second={average:.2f}")
print(f"peak_reads_per_second={peak:.2f}")
for hit_fraction in [0.90, 0.0]:
print(f"hits={hit_fraction:.0%}, origin_reads={peak*(1-hit_fraction):.2f}/s")
print(f"peak_creations={10000/86400*5:.3f}/s")
Expected output
average_reads_per_second=11.57
peak_reads_per_second=57.87
hits=90%, origin_reads=5.79/s
hits=0%, origin_reads=57.87/s
peak_creations=0.579/sThe cache changes modeled origin reads, not external redirects or creation writes. Real capacity requires measured per-operation costs and retry behavior in addition to these rates.
05 Cheat sheet
Review the decisions
Use this table to explain the mechanism and its limit without memorizing a product name.
| Choice or concept | Remember | Check |
|---|---|---|
| Users × actions | Daily requests | Registered users are not DAU |
| Daily requests / 86,400 | Average QPS | Average can hide events |
| Average × peak factor | Modeled peak | The factor needs evidence |
| Misses × read QPS | Database read rate | Not the same as external QPS |
06 Where & why
Check the primary references
Use official references for protocol and implementation details. The questions here are teaching prompts.
07 Interview questions
Explain the reasoning out loud
Answer before opening the explanation. The questions progress from vocabulary to decisions and failure behavior.
What does DAU mean?
What does QPS mean?
What does Peak factor mean?
Why ask whether users are daily or monthly active?
Why keep reads and writes separate?
Can one request mean several database queries?
Is the highest daily average a reliable launch peak?
Why avoid rounding every intermediate step?
08 Practice problems
Practice a new case
Solve the new cases before revealing hints. Complete worked solutions follow the set.
Daily requests
EasyShow the hint
Daily actions
EasyShow the hint
Separate traffic
MediumShow the hint
Peak model
MediumShow the hint
Launch event
MediumShow the hint
Capacity memo
HardShow the hint
Worked solutions
1. Daily requests
8,640,000 / 86,400 = 100 read QPS.
2. Daily actions
30,000 × 12 = 360,000 reads/day.
3. Separate traffic
Reads average 10 QPS; writes average 0.1 QPS.
4. Peak model
4,320,000 / 86,400 = 50 QPS average; modeled peak is 300 QPS.
5. Launch event
48,000 requests / 8 seconds = 6,000 QPS during the event.
6. Capacity memo
16 million daily reads / 86,400 = about 185.19 average QPS, 740.74 peak QPS, and 74.07 database read QPS after caching. These do not prove sharding is necessary. Measure query cost, write load, storage size, hot keys and failure capacity before splitting data.