Bonus A

Estimation for System Designers

July 22, 202614 min readBy Ashutosh Singh

"How many servers would this need?" The question that freezes more candidates than any algorithm.

Way back in Part 3, the C.R.E.D framework promised that Estimate comes before Design. Part 3 explained why. It never fully taught how — and nine articles of homework have been piling up since: cache sizing (Part 6), message rates (Part 7), storage growth (Part 8), traffic skew (Bonus G), fleet and pool math (Part 9).

Part 12 closed the building blocks and pointed here: before we design real systems, the E finally gets its article.

Here's the reframe that removes the fear: estimation is not about predicting the future perfectly. It's about converting vague requirements into approximate numbers — so architecture decisions have scale, direction, and boundaries instead of vibes.

The Simple Mental Model: Counting Vehicles Before Building the Road

Before building a road or a flyover, nobody knows the exact number of vehicles that will pass every minute for the next ten years. But the builders must know enough: is this a village road or a highway? Is peak traffic 100 vehicles/hour or 100,000? Are the vehicles mostly bikes, cars, or trucks? Will traffic grow every year? What happens during festivals, office hours, or match days?

Get those five answers roughly right, and you build the right class of road. Get them wrong, and you build a footpath for highway traffic, or a six-lane expressway for a lane that serves forty scooters a day.

System estimation is exactly this. Not perfect numbers. Numbers good enough to pick the right class of system.

Estimation Is Not Guessing

The difference between guessing and estimating is structure. Estimation is structured approximation, built from: explicit assumptions, written down and challengeable ("assume 1M DAU, 20 actions each"); simple formulas, multiplication and division, nothing an interview whiteboard can't hold; round numbers (86,400 seconds/day becomes ~100,000 — the error is 15%, the mental speed is 10×); order-of-magnitude thinking (the question is never "is it 230 or 260 QPS?" it's "is it hundreds, thousands, or millions?" — architectures change between magnitudes, not between neighbors); sanity checks (does the answer pass the smell test against systems you know?); and visible trade-offs (every number points at a design consequence).

And the rule that makes estimation safe to do out loud: a wrong-but-clear assumption is better than a hidden assumption. A stated assumption can be corrected in ten seconds. A hidden one gets discovered in production, expensively.

The Core Estimation Units

The vocabulary — thirteen numbers that describe almost any system:

UnitWhat it measuresWhy it matters
DAUDaily active usersThe traffic source
MAUMonthly active usersGrowth and engagement (DAU/MAU = stickiness)
QPSRequests per secondThe load, averaged
Peak QPSWorst-hour loadWhat actually breaks systems
Read/write ratioReads per writeThe single biggest architecture-shaper
Average payload sizeBytes per request/responseFeeds bandwidth math
Object/file sizeBytes per stored thingFeeds storage math (Part 8)
Retention periodHow long data livesMultiplies everything
Replication factorCopies keptMultiplies storage (Bonus I)
Cache hit rate% served from cacheDivides backend load (Part 6)
Fan-out factorDownstream work per action1 post × 5,000 followers = 5,000 writes (Part 16's whole problem)
ConcurrencySimultaneous in-flight workSizes pools and workers
Latency budgetTime allowed, end to endDivided among every hop

Every estimation below is these units, multiplied.

From DAU to QPS

The most common conversion in system design, worked in full:

Assume:  1,000,000 DAU
         20 actions per user per day

Requests/day  = 1M × 20            = 20,000,000
Seconds/day86,400 (call it ~100,000 for speed)
Average QPS   ≈ 20,000,000 / 86,400230
Peak factor   = 5× (traffic clusters — evenings, lunch, match day)
Peak QPS      ≈ 230 × 51,150

Two habits hiding in that block. The ~10⁵ trick: a day is roughly 100,000 seconds, so millions per day ÷ 100K = tens per second — 20M/day → ~200 QPS, instantly, in your head. Refine later if it matters. And always announce the peak: average QPS is a bookkeeping number. Systems fail at peak, not at average — the road handles Tuesday 3 AM fine, it's the festival evening that matters. State your peak factor (3–10× is typical, workload-dependent) as an explicit assumption, and design for that number.

Read/Write Ratio: The Number That Changes Architecture

If you can only estimate one ratio, estimate this one, because entire architectures pivot on it. URL shortener: enormous reads, trickle of writes — a caching problem wearing a database costume. Social feed: read-heavy and fan-out-heavy — every write multiplies (Part 16 awaits). Chat app: write-heavy with real-time reads — the broker earns its keep (Part 7). Analytics dashboard: few writes, brutal read aggregations — precomputation territory. Banking ledger: modest write volume, zero tolerance for write errors — consistency outranks throughput (Bonus F).

And what the ratio decides:

Ratio leans…The design leans…
Read-heavyCaching layers (Part 6), read replicas (Bonus I), CDN
Write-heavyWrite-path design, sharding + key choice (Bonus G), queues to absorb bursts (Part 7)
Both heavyAll of the above, plus the consistency conversation (Bonus F) — per data type

100:1 reads and 1:1 reads are different systems that happen to share a feature list.

Storage Estimation

One formula covers most of it:

Storage ≈ records × average size × retention × replication/overhead

Feel it with different data shapes: URL mappings, ~500 bytes each, metadata-class data — even hundreds of millions stay in gigabytes. User profiles, a few KB — still database territory (Blog 5). Logs/events, tiny each, relentless in volume — retention is the whole cost story (Part 12's sampling exists for this). Uploaded files, MBs to GBs each — blob-class, object storage + metadata split (Part 8), and file size dominates every other term.

The multipliers engineers forget, in rising order of embarrassment: compression (logs shrink dramatically), replication factor (×3 is the classic — Bonus I's copies aren't free), retention (×36 months turns cute into serious), growth (this year's rate is next year's floor), and backup/archive overhead (Part 8: different job, additional bytes).

Estimate raw first. Then multiply honestly.

Bandwidth and Egress Estimation

Bandwidth is payload × rate, and it converts directly into money (Part 8's egress line item):

1,000 requests/sec × 50 KB each = 50 MB/sec
                                ≈ 4.3 TB/day leaving the system

Four terabytes a day is a bill, not a detail.

Which is why the CDN hit rate belongs in this arithmetic: at a 90% edge hit rate (Part 6, layer 2), the origin serves one-tenth of that, the caching stack quietly working as a financial instrument. Large files flip the equation entirely: one video view can outweigh ten thousand API calls, which is why Part 8 paired object storage with the CDN before the first byte shipped.

Cache Sizing and the Hot Working Set

The estimation mistake: sizing the cache for the dataset. The correction: size it for the hot working set, because traffic is never uniform (Bonus G made a whole article of this).

Assume: 10% of URLs serve 90% of traffic

Then a cache holding just that 10%
captures ~90% of readsand the database sees one-tenth of the load.

The inputs: total dataset size, the hot fraction, target hit rate, object size, TTL (Part 6's freshness dial), and the read/write ratio (caching write-heavy data is decoration — Part 6 said it first).

One skew warning from Bonus G: if a single key is the hot set — the celebrity, the viral link — the estimate changes shape. That's not a sizing problem, it's a hot-key problem.

Queue and Worker Estimation

For anything async (Part 7), the arithmetic is supply vs. demand:

Required workers ≈ peak messages/sec ÷ messages/sec one worker processes

Producers emit:        10,000 messages/sec at peak
One worker processes:  500 messages/sec
Workers needed ≈ 10,000 / 500 = 20 — plus headroom

And the number teams forget until the incident: drain time.

Drain time = backlog ÷ (worker capacity − incoming rate)

A million-message backlog with 2,000 msg/sec of spare capacity drains in ~8 minutes. With 100 msg/sec spare: nearly 3 hours. Same backlog, different day. Add retry volume on top (failures resubmit work — Bonus E's amplifier), and set the DLQ expectation as a number, not a hope.

This is also the autoscaling signal math from Part 9: queue depth and lag, quantified.

Compute and Connection-Pool Estimation

Fleet sizing is rough by nature, and still catches disasters early: requests/sec per instance (measured or assumed — state it), CPU-bound vs. I/O-bound (Part 9's distinction — I/O-bound instances wait more and handle more concurrency than CPU suggests), autoscaling headroom (the burst outruns the boot time, Part 9 — estimate the gap the queue or the users will absorb), and cold starts / warm-up (new instances underperform briefly — Part 6's cold caches).

And the single most valuable multiplication in this article — the one Part 9 turned into a stampede story:

Max fleet:        30 instances
DB pool each:     20 connections
30 × 20 = 600 possible database connections
Database safely supports: 300

→ The design fails at scale-outby arithmetic, before any code exists.

Fix the pool sizes, add pooling infrastructure, or change the architecture — but decide now, on paper, for free.

Downstream limits bound your compute estimate. Always run the multiplication one layer below the thing you're scaling.

Latency Budget Estimation

A "500 ms API" is not one number. It's an allowance to be divided:

HopBudget
Gateway (Part 10)10 ms
Auth check (Part 11)20 ms
App logic50 ms
Cache lookup (Part 6)5 ms
Database query100 ms
External dependency200 ms
Network + serialization40 ms
Total425 ms — 75 ms headroom

The trap this table exists to prevent: every downstream team assumes they have "just 200 ms," and five such calls is a full second, double the promise, before anything goes wrong. (Part 7's answer applies: what can leave the synchronous path, should.)

Budget the p99, not the average (Part 12) — the tail is where the promise is actually kept or broken.

Mini Estimation: URL Shortener

Time to put every tool on one small problem — the exact problem Blog 13 will design in full. We estimate today; we design next time.

The assumptions, stated:

New short URLs:   10 million/month
Reads per write:  100
Record size:      ~500 bytes (mapping + metadata)
Retention:        3 years
Peak reads:       10× average

The arithmetic:

WRITES
  10M/month ÷ 30333,000/day
  ÷ ~100,000 sec        ≈ 4 writes/sec        ← almost nothing

READS
  333K × 10033 million/day
  ÷ 86,400385 QPS average
  × 10 peak             ≈ ~4,000 QPS at peak  ← the real problem

STORAGE
  10M × 36 months       = 360M records
  × 500 bytes           = 180 GB raw
  × 3 replication       ≈ ~540 GB             ← comfortably one database

CACHE
  Hot 10% of records    ≈ 36M × 500 B ≈ 18 GB
  → the hot set fits in one modest cache node,
    and at 90% hit rate the DB sees ~400 QPS at peak

Now read what the numbers say. The read/write ratio (100:1) declares this a read-serving problem, not a write problem — Part 6's whole playbook applies. Storage is a non-issue: half a terabyte over three years is one database, not a fleet. The write path is so light that the interesting write question isn't throughput — it's key generation (how do 4 writes/sec get unique short codes without collisions?). Hold that thought for Blog 13. And peak read QPS (~4,000) is the number the design must answer, with the cache, and read replicas if needed.

Four assumptions, five multiplications, and the architecture's shape is already visible before a single box is drawn. That is what estimation buys.

How Estimation Changes Architecture Decisions

The whole point, on one table:

The estimate says…The design leans…
Low QPSA simple, stateless monolith may be plenty (Part 9's underrated option)
High read ratioCaching layers and read replicas (Parts 6, Bonus I)
High write ratioSharding + key design, queues to absorb bursts (Bonus G, Part 7)
Large filesObject storage + CDN from day one (Part 8)
High fan-outMessaging and async processing (Part 7; Part 16 ahead)
Strict latencyFewer synchronous hops, aggressive cache design (Parts 6, 7)
Long retentionLifecycle tiers and cost planning (Part 8)
Tight p99 requirementTail-latency design and real observability (Part 12, Bonuses E/G)

Estimates Meet Reality

One more discipline, and it closes a loop with Part 12: an estimate is a hypothesis, and your dashboards are the experiment. When production metrics arrive, revisit the assumptions — actual DAU, actual peak factor, actual hit rate. The gap between estimated and observed isn't embarrassment; it's calibration. Teams that never revisit are still designing for a system that doesn't exist.

In C.R.E.D terms, this article is the E — the bridge between Requirements and Design, crossed with arithmetic instead of adjectives.

A good architect does not ask only, "What technology should we use?" A good architect asks, "How many users, requests, writes, reads, bytes, peaks, and failures are we designing for?"

Common Mistakes Engineers Make with Estimation

Trying to be exact instead of useful — the magnitude is the answer, the decimals are theater. Not stating assumptions — a hidden assumption is a production incident on layaway. Estimating average, ignoring peak — systems fail on festival evening, not Tuesday 3 AM. Ignoring the read/write ratio — the one number that picks the architecture. Ignoring payload size — 1,000 QPS of 1 KB and 1,000 QPS of 5 MB are different businesses. Ignoring retention — ×36 months turns every cute number serious. Forgetting replication and backup overhead — the ×3 that triples the "final" answer. Skipping bandwidth and egress — the estimate with a currency symbol (Part 8). Ignoring fan-out — one action, five thousand consequences. Ignoring retries — failure adds traffic exactly when capacity drops (Bonus E). Skipping the connection-pool multiplication — 30 × 20 vs. 300, the outage you could have computed. Assuming uniform traffic — Bonus G's hot keys laugh at your averages. Estimating once, never revisiting — production data arrived, the design doc didn't notice. Designing for imaginary scale — ten million users in the deck, four hundred in production, the expressway for forty scooters.

From My Journey: An Architectural Lesson

Many engineers feel genuinely nervous during estimation — in interviews and in design reviews alike — because of one quiet belief: that the interviewer or the stakeholder expects exact numbers, and anything less will be exposed as guessing.

Real architecture work dissolves that belief quickly. Exact numbers are almost never available early. There is no traffic report for a product that hasn't launched. And yet the decisions can't wait — databases, caches, queues, storage, compute, and budgets all get chosen anyway.

The realisation that changes the relationship with estimation: its value was never precision. Its value is direction. A half-page of stated assumptions and rounded multiplication tells you whether the system is small or large, read-heavy or write-heavy, storage-bound or latency-bound, cheap or expensive — and each of those answers eliminates half the design space.

The trade cuts both ways, and staying honest is the skill. Estimate too little, and the system is under-designed — the footpath meeting highway traffic. Estimate imaginary scale, and it's over-engineered — complexity purchased for users who never arrive. Good estimation stays humble about the numbers and loud about the assumptions.

The lesson that stuck: estimation is not a math test. It is architecture's reality check.

Estimation does not predict the future. It prevents architecture from pretending scale does not exist.

Key Takeaways

  • Estimation converts vague requirements into approximate numbers — direction and magnitude, not decimals.
  • A wrong-but-clear assumption beats a hidden one: state it, round it, sanity-check it.
  • A day is ~100,000 seconds: millions/day ÷ 10⁵ = tens/second, in your head.
  • Design for peak, not average — and announce your peak factor as an assumption.
  • The read/write ratio is the single biggest architecture-shaper; 100:1 and 1:1 are different systems.
  • Storage = records × size × retention × replication — and the multipliers are where estimates go to die.
  • Bandwidth is payload × rate, and it converts to money; the CDN hit rate is a financial instrument.
  • Size the cache for the hot working set, not the dataset; size workers by throughput ÷ capacity, and know your drain time.
  • Run the multiplication one layer down: fleet × pool vs. database limit catches the outage on paper.
  • Estimates are hypotheses; dashboards (Part 12) are the experiment. Revisit and recalibrate.

Interview Lens

Estimation is where interviews are quietly won — not because the numbers impress, but because the ritual signals a working engineer.

The four-step ritual, out loud: "Let me assume 1M DAU and 20 actions each — correct me if the scale's different. That's 20M requests/day; a day is roughly 10⁵ seconds, so ~200 QPS average. Traffic clusters, so call peak 5× — about 1,000 QPS. Reads dominate maybe 100:1, so this is a caching problem first."

State the assumption. Round aggressively. Compute simply. Announce the peak and the ratio unprompted — that last move is the differentiator, because it shows you know which numbers drive design.

Expect the probes: "Is that a lot?" — calibrate against magnitude: hundreds of QPS is a modest, well-cached single database's afternoon; hundreds of thousands is a different article. "What if you're wrong by 10×?" — the right answer: "then the magnitude changes and so does the design, which is exactly why I stated the assumption where you could challenge it." "How much storage?" — walk the formula, and say "times replication" before they do.

The failure mode interviewers watch for: silence, then a technology name. The pass: assumptions, arithmetic, and a conclusion the numbers actually support.

Real-World Engineering Lens

Put an estimation block in every design doc. Half a page: assumptions, QPS, ratio, storage, peak, the pool multiplication. Reviewers challenge numbers far more usefully than adjectives.

Run the one-layer-down multiplication in every review. Fleet × pool vs. downstream limit. Two minutes; occasionally saves a quarter.

Calibrate quarterly. Estimated vs. observed — DAU, peak factor, hit rate — side by side on the Part 12 dashboards. Update the doc; keep the diff. That history is your team's growing intuition, written down.

Apply the imaginary-scale check. Design for the next 10×, architect awareness for 100×, and build for neither beyond that — Part 2's simplicity lesson, with numbers attached.

What's Next

We can count now. Next: how requirements become architecture.

Bonus B — NFR to Architecture: How Constraints Drive Design Decisions. The causal chain the series has gestured at since Part 3 — "availability requirement → replication and failover" — finally traced end to end. Then Bonus C (the three kinds of trade-offs) and Bonus H (polyglot persistence) — and then Blog 13 takes everything, including today's URL-shortener numbers, and draws the boxes.

Question for Readers

Without looking at any dashboard: estimate your main API's requests per day, its peak QPS, and its read/write ratio.

Now go check (Part 12 gave you the tools).

The gap between your estimate and reality is your calibration homework — and shrinking it is a skill that compounds for the rest of your career.