Capacity estimation

Assumptions first, a day as 100,000 seconds, storage and bandwidth — and the numbers to know, measured: a map lookup in nanoseconds, a real network hop a million times slower.

5 min read🏗️ System Design Fundamentals

Capacity estimation is the arithmetic that turns "a lot of users" into numbers a design can be judged against: requests per second, bytes stored, bytes sent. It is not about being right to three significant figures. It is about being right to within a factor of ten, quickly, with every assumption written down where someone can disagree with it.

The skill is not multiplication. It is knowing which numbers to compute, stating what you assumed to get them, and recognising which result changes the design.

Assumptions first, always

Every estimate starts from numbers nobody measured. That is fine, as long as they are labelled as assumptions:

plaintext
assume   100 million registered users, 10% active on a given day
assume   each active user makes 20 requests a day
assume   peak traffic is 3× the daily average
assume   each request writes 1 KB of data 10% of the time

Written this way, a disagreement is productive. "Your 10% daily active is high for this product" changes one line, and everything below it follows. An estimate that presents "about 7,000 requests a second" without its inputs can only be accepted or rejected whole.

From users to requests a second

The conversion everyone needs, and the one constant worth memorising: a day has 86,400 seconds, which is close enough to 100,000.

plaintext
active users per day      100M × 10%                 = 10M
requests per day          10M × 20                   = 200M
average per second        200M / ~100,000            ≈ 2,000
peak per second           2,000 × 3                  ≈ 6,000

With 86,400 the average is 2,315. The rounding changed the answer by 15%, which changes no decision. Using 100,000 is what makes the arithmetic fast enough to do out loud.

Two shortcuts that come from the same constant:

  • 1 million requests a day is about 12 a second. (1M / 86,400 = 11.6.)
  • 1 request a second is about 2.6 million a month.

Always carry the peak, not the average. Systems are sized for the worst hour, and the ratio between peak and average is a real property of the product — close to 1 for background jobs, easily 5–10 for anything tied to human schedules, and far more for a ticket sale that opens at a fixed time.

Storage

plaintext
writes per day           200M requests × 10%          = 20M
bytes per day            20M × 1 KB                   = 20 GB
bytes per year           20 GB × 365                  ≈ 7 TB
with 3 replicas          7 TB × 3                     ≈ 20 TB

Then ask what that number means. 7 TB a year fits on one large database server for a year or two; 20 TB replicated is still modest. The design consequence is that nothing here forces sharding yet — and saying so is as useful as finding the number that does.

Remember what the raw figure leaves out: indexes (often as large as the data), replication, backups, and growth. A factor of 2–3 over the raw bytes is a reasonable first allowance, stated as an assumption like everything else.

Bandwidth

plaintext
average response         10 KB
peak egress              6,000 req/s × 10 KB           = 60 MB/s ≈ 500 Mbit/s

Bandwidth estimates matter most where the payload is large — images, video, file downloads — and that is usually where they change the design: towards a CDN, towards object storage serving bytes directly, and towards the cost line, because egress is often the most expensive thing a large system pays for.

The numbers to know

To judge whether a design can meet its latency, you need a sense of what things cost. Tables of "latency numbers every programmer should know" are widely reproduced; the orders of magnitude are what matter, and they are worth checking on real hardware rather than reciting. These were measured on one laptop, in a Docker container, with the best of five runs:

plaintext
HashMap.get, 1M entries                          36.0 ns
Jackson: serialize a small object               180.0 ns
SHA-256 of 1 KB                                 464.0 ns
copy 1 MB within memory                          42.7 µs
write 4 KB and fsync (container disk)            66.0 µs
TCP round trip over loopback, 1 byte             29.4 µs

And one real network hop — a TCP connection from that laptop to this site's production server, five times:

plaintext
0.034 s   0.043 s   0.035 s   0.035 s   (first: 0.079 s, including a DNS lookup)

Read them as ratios, because the ratios are what transfer to other hardware:

operationroughlyrelative to a map lookup
in-memory lookuptens of nanoseconds1
serialize a small objecthundreds of nanoseconds~5
round trip on the same machinetens of microseconds~1,000
round trip to a server in another citytens of milliseconds~1,000,000

The last line is the one that designs systems. A network hop between cities costs about a million in-memory lookups. A request path that calls five services in sequence, each a few milliseconds away, has spent its latency budget on the network before any of them did any work.

Which result changes the design

Once the numbers exist, the question is which of them crosses a threshold. The thresholds below are rough, and they are assumptions to state, not laws:

if the estimate saysthe design needs to consider
writes beyond what one primary database handles comfortablypartitioning, or a write-optimised store
data beyond one machine's disk for the retention periodsharding, or tiering old data to object storage
reads far outnumber writescaching and read replicas, and their staleness
large payloads at high ratesa CDN and object storage in the data path
a latency budget smaller than the network hopsfewer hops, co-location, or asynchronous work

An estimate that crosses none of them is also a result: the simple design works, and the deep dive should go somewhere else. The worked designs on the System Design page each end their estimation with a line saying which number mattered and which did not, which is the habit to copy.

Progress is saved on this device and to your account when signed in.