Skip to content

System DesignFundamentals

Back of the envelope estimation

Back of the envelope estimation for system design interviews, with QPS, peak, storage, bandwidth, cache and server math, latency numbers and worked examples.

Foundation33 min core · 36 min full depth

A back of the envelope estimate turns a product description (“100 million people use it every day”) into the handful of numbers that pick an architecture:

  • Requests a second at peak.
  • Bytes stored after five years.
  • Bytes a second on the wire.
  • Memory for the hot set.
  • Machines.

It takes two to four minutes, and uses one or two significant figures. It’s judged by one thing: whether each number leads to a decision. Every worked problem on this site opens its capacity estimates this way.

Two engineers design the same chat service. One assumes “a lot of messages”, and draws a single PostgreSQL primary behind a cache. The other spends ninety seconds on arithmetic. 500 million users × 40 messages a day is 20 billion a day. That’s about 230,000 writes a second, and near 700,000 at the evening peak. One PostgreSQL primary sustains about 10,000 indexed writes a second. So the first design is off by seventy times, and no tuning closes that gap. The second engineer knew, before drawing a box, that writes must be partitioned.

Designs change at orders of magnitude, not at percentages:

If the number is about… …the design is
100 writes a second One database, no discussion
10,000 writes a second One well-tuned primary, close to its limit
1,000,000 writes a second A partitioned store across dozens of nodes
10 GB of data Fits in RAM on one box: cache all of it
10 TB One database cluster, partitioning on the horizon
10 PB Object storage with tiering, cost is the design

An estimate within a factor of two or three lands in the right row. One off by ten picks the wrong row, and everything drawn after it is wrong. The skill is not precise arithmetic but knowing a few reference numbers well enough to land in the right row fast.

The method is a chain. Users become requests. Requests become a peak. The peak splits into reads and writes. And each of those becomes storage, bandwidth, memory and machines. Each link is one stated assumption and one multiplication.

The estimation chain, and the decision at the end of each link

÷ 10^5

× peak factor

× bytes × days × copies

× response bytes

× one fifth × item bytes

÷ per-server rate

Daily users
× actions each

Requests a day

Average per second

Peak per second

Reads at peak

Writes at peak

Cache or replicas?

One primary or shards?

Storage

One node, shards, or object storage?

Bandwidth

One NIC, many, or a CDN?

Cache memory

One cache node or a cluster?

Servers

÷ 10^5

× peak factor

× bytes × days × copies

× response bytes

× one fifth × item bytes

÷ per-server rate

Daily users
× actions each

Requests a day

Average per second

Peak per second

Reads at peak

Writes at peak

Cache or replicas?

One primary or shards?

Storage

One node, shards, or object storage?

Bandwidth

One NIC, many, or a CDN?

Cache memory

One cache node or a cluster?

Servers

Scroll or pinch to zoom, drag to pan
  • Color key
  • What you are given
  • A number you work out
  • The decision it drives

Time. A day has 86,400 seconds. Round it to 10^5. Dividing by 100,000 instead of 86,400 understates the rate by 14%. That’s far less than the error in any traffic assumption. And it turns every per-day figure into a per-second figure, by shifting the decimal point five places.

Period Seconds So 1 million per period is And 1 per second is
Day 86,400 ≈ 10^5 about 12 a second about 100,000 a day
30 days 2.6 million about 0.4 a second 2.6 million a month
Year 31.5 million ≈ π×10^7 about 0.03 a second 30 million a year

Two shortcuts follow: 1 billion a day is about 12,000 a second, and 1 billion a year is about 30 a second.

Powers of two and ten. Every 10 powers of two are about 3 powers of ten. That one fact converts between bits of an ID and how many things it can name.

Power of 2 Exact or rough value ≈ Power of 10 Shows up as
2^10 1,024 10^3 KiB, “a thousand”
2^20 1.05 million 10^6 MiB
2^30 1.07 billion 10^9 GiB
2^32 4.3 billion Every IPv4 address, a 32-bit auto-increment ID
2^40 1.1 trillion 10^12 TiB
2^63 9.2 × 10^18 The largest signed 64-bit integer (bigint)
2^64 1.8 × 10^19 A 64-bit ID: never runs out

A signed 32-bit ID (PostgreSQL integer) runs out at 2.1 billion rows. A busy table reaches that in a few years. That’s why IDs are 64-bit by default. The unique IDs page uses the same arithmetic for timestamp bits and sequence bits.

Sizes. Text is small, and media is huge. A comment or message row, with its metadata and index entries, is 200 bytes to 1 KB. A display photo is 100 to 500 KB. A minute of 1080p video is 40 to 60 MB. In any system that stores photos or video, media dominates storage and bandwidth by a factor of a hundred or more. The text rows round to zero.

Go deeperTypical sizes to carry1 min
Thing Typical size
An integer ID, a timestamp 8 bytes
A UUID 16 bytes binary, 36 as text
A short text row (a message, a comment) with metadata and index entries 200 bytes to 1 KB
A JSON API response 1 to 10 KB
A log line 200 bytes to 1 KB
A web photo, compressed for display 100 to 500 KB
A phone photo, original 2 to 5 MB
One minute of 1080p video at 5 to 8 Mbps 40 to 60 MB

Latency. The gaps between rungs matter more than any one value. A memory read is about a thousand times faster than an SSD read. An SSD read is a few times faster than a same-zone round trip. And that’s a few hundred times faster than one across an ocean.

Latency budget

    Each bar is on a log scale: one step right is ten times slower. Click a rung for what it means in a design.

    Things to try:

    • Set the budget to 1 ms. The red rungs are what one request cannot afford even once: a disk seek, any cross-region call.
    • Set it to 100 ms, roughly what a click can spend before it stops feeling instant. It fits one transatlantic round trip, or about 400 same-zone hops: ten sequential service calls are cheap inside a data center and ruinous across regions.
    • Read the “if 1 ns were 1 s” line. A memory read is under two minutes. An SSD read is a day. A round trip to Australia is eight years.
    • Open the number drill. Within 3× of the exact answer counts: that is the precision a design needs.

    Throughput per node. Order-of-magnitude planning figures, not benchmarks: they move by several times with row size, query shape and configuration. Use them to decide between one node and fifty.

    Component Order of magnitude per node
    Stateless API server, 8 to 16 cores 1,000 to 10,000 requests/s; plan 1,000 to 5,000 with real work
    PostgreSQL or MySQL primary About 10,000 indexed write transactions/s
    PostgreSQL or MySQL, reads Tens of thousands to a few hundred thousand cached point reads/s
    Redis shard 100,000 to 200,000 simple commands/s, over 1 million pipelined
    Kafka broker Hundreds of MB/s; tens of MB/s per partition
    Cassandra or ScyllaDB node 10,000 to 30,000 writes/s
    WebSocket gateway 100,000s of open connections
    One server NIC 10 to 25 Gbps, that is 1.25 to 3 GB/s
    Usable RAM on a cache node About 100 GB
    Comfortable size of one SQL database node A few TB; restores and upgrades get slow past 5 to 10 TB

    The databases and caching pages carry the same figures with more detail per store.

    Start from people, not requests: “100 million daily active users” is a statement about a product that someone can confirm or correct. Then count actions per user a day, and multiply.

    The running example on this page is a comments service: 100 million daily users, each making 20 requests a day (opening threads, loading more, posting).

    100 million users × 20 requests = 2 billion requests a day
    2 × 10^9 ÷ 10^5 = 20,000 requests a second on average

    The exact answer is 23,000. Nobody needs it.

    Two traps live here:

    • Monthly and daily users differ, by two to five times for most products. So using MAU as DAU inflates every number downstream.
    • One user action is not one request. Opening an app can fire ten API calls. Typeahead sends about 6 requests per search. That turns 36,000 searches a second at peak into 210,000 requests.

    Capacity is bought for the peak, not the average. A consumer product is quiet at 4 a.m., and busy in the evening. The busiest hour typically runs 2 to 3 times the daily average. Global products smooth this a little. Events break it entirely.

    Source of peak Typical multiple over average Example on this site
    The daily curve 2 to 3× News feed: 58,000 loads a second average, 170,000 at the evening peak
    Weekly and seasonal (Black Friday, New Year’s Eve) 3 to 10× Chat on holidays
    A scheduled event (an on-sale, a launch, a broadcast) 10 to 1,000× on one feature Ticketmaster: 2 million people arrive for 50,000 seats in the same minute
    One viral item Most of the load on one key URL shortener: one code in a Super Bowl ad
    20,000 a second × 3 = 60,000 requests a second at peak

    The last row is different in kind. A viral key does not raise the total much. But it concentrates it on one shard, one cache node or one database row. The estimate that matters is “how much traffic can one key get?” The answer leads to replicated hot keys or a CDN, not to more shards. The partitioning page covers hot keys.

    Reads scale by copying data into replicas, caches and CDNs. Writes must reach the one place that owns the data, so they scale only by partitioning. The ratio decides which half gets the attention.

    Read to write ratio Shape Examples Where the effort goes
    100 to 1 or more Read-heavy URL shortener, product catalog, Pastebin views Caches, replicas, CDN
    10 to 1 Mostly reads Comments, social feeds (counting reads per post) Cache, then write partitioning later
    About 1 to 1 Balanced Chat (each message is written once, read by a few devices) Both paths, partitioned from day one
    1 to 10 or less Write-heavy Metrics, logs, ad clicks, IoT telemetry Batched, partitioned, append-only writes

    For the comments service, at 10 reads per write:

    writes at peak: 60,000 ÷ 11 ≈ 5,500 a second (one primary, about half its capacity)
    reads at peak: 60,000 − 5,500 ≈ 55,000 a second (more than a few replicas want: cache in front)

    Storage is new records a day × bytes each × days kept × copies:

    writes a day: 2,000 a second on average × 10^5 = 200 million
    bytes a day: 200 million × 500 bytes = 100 GB
    over 5 years: 100 GB × 365 × 5 ≈ 100 GB × 1,800 = 180 TB
    three copies: 180 TB × 3 ≈ 550 TB

    The pieces people forget:

    • Bytes per record includes everything. A 140-character comment also carries IDs, timestamps, an author and index entries. Budget 2 to 3 times the payload for a small row, then round (500 bytes here).
    • Replication multiplies. Three copies is the default for replicated databases. Backups are extra copies too.
    • Disks are not filled to the top. Plan to run at about 70% full, so compaction, vacuum and growth have room. 550 TB of data wants about 800 TB of disk.
    • Retention and compression divide. A 90-day hot window changes the answer by a factor of twenty. That’s why the chat problem moves older history out of its database. Text compresses 3 to 10 times. Photos and video do not.

    Keep one shortcut: 365 × 5 ≈ 1,800, so “per day” becomes “per five years” by multiplying by about 2,000.

    Bandwidth is the peak rate times bytes per request or response, separately for ingress and egress. Egress is almost always larger and is what cloud providers charge for.

    egress at peak: 60,000 responses a second × 10 KB = 600 MB/s
    in bits: 600 MB/s × 8 = 4.8 Gbps

    Networks are rated in bits, and storage in bytes. So convert explicitly: × 8 from bytes to bits. At 4.8 Gbps, the comments service fits under one 10 Gbps NIC, and it’s spread across many servers anyway. So bandwidth is not a design driver: say so, and move on. With media, it is the design, as worked example 3 shows.

    Most reads go to a small share of items: the newest posts, the trending video. The working rule is Pareto’s: about 20% of items get 80% of reads, so caching 20% of a day’s reads catches most traffic.

    reads a day: 20,000 a second × 10/11 × 10^5 ≈ 1.8 billion
    cache 20%: 1.8 billion × 0.2 × 500 bytes ≈ 180 GB

    This is a loose upper bound: it counts read requests, not distinct items, and a hot set is the same items read again and again. It still answers the question that matters: 180 GB is more than one cache node’s 100 GB, so plan a small sharded cluster. The caching page covers hit ratios.

    Servers are the peak rate divided by what one server handles at the planned utilization:

    app servers: 60,000 ÷ 2,000 a second each = 30
    across 3 zones, survive losing one: 30 × 1.5 = 45

    Two things set “what one server handles”. First, the per-node table, taken at a utilization of 50 to 70%, not 100%. In a simple queue, the wait grows with ρ ÷ (1 − ρ). So at 80% busy, a request waits four times its service time. At 90%, it waits nine times.

    Second, Little’s law: requests in flight = arrival rate × time each spends in the system. At 60,000 requests a second and 50 ms each, 3,000 requests are in flight across the fleet, 100 per server. If each holds a database connection for 5 ms, the database sees 60,000 × 0.005 = 300 connections in use. The same law sizes thread pools and connection pools.

    Redundancy is part of the count. Losing one of three zones leaves two thirds of the fleet, so provision 1.5 times the need, plus room for a rolling deploy.

    Rounding rules.

    • Keep one or two significant figures and write numbers as a mantissa and a power of ten. Multiply the mantissas and add the exponents: 2 × 10^8 rows × 5 × 10^2 bytes = 10 × 10^10 = 10^11 bytes, 100 GB.
    • Round early, in the safe direction: up for load, sizes and copies, down for what one machine handles.
    • Carry units on every number, then convert once. Most estimation errors are unit errors.
    • Errors in independent assumptions partly cancel, but a chain of seven factors each 1.5 times too high is 17 times too high. If several assumptions are generous, say so and trim one.

    Sanity checks. Check the answer a second way:

    • Divide back per user. 550 TB over 100 million users is 5.5 MB each. At 500 bytes and three copies, that’s two comments a day for five years. Plausible for active users, but wrong for a weekly app.
    • Compare with something public. Google search is widely reported at about 8.5 billion a day, about 100,000 a second. WhatsApp reported 100 billion messages a day in 2020, over a million a second. A new product that beats either has a wrong assumption.
    • Check against one machine. If the whole system fits on one server with room to spare, the honest design is one server plus a replica. The hard part is somewhere else.

    When to stop. Each number does one of two things. It crosses a threshold and forces a decision: more writes than one primary, more data than one node, more egress than one NIC. Or it sits an order of magnitude away from every threshold, and is declared irrelevant.

    Is this estimate worth more time?

    No, 10x below

    No, 10x above

    Yes, close

    A number, rounded to one or two figures

    Within 3x of a threshold?
    one primary, one node, one NIC, one box of RAM

    Say it does not matter. Move on.

    Decision is clear. Name it. Move on.

    Refine the one assumption
    that drives it, or design for both sides

    No, 10x below

    No, 10x above

    Yes, close

    A number, rounded to one or two figures

    Within 3x of a threshold?
    one primary, one node, one NIC, one box of RAM

    Say it does not matter. Move on.

    Decision is clear. Name it. Move on.

    Refine the one assumption
    that drives it, or design for both sides

    Scroll or pinch to zoom, drag to pan
    • Color key
    • What you have
    • A question to ask
    • Stop and move on

    The calculator holds the comments service. A highlighted row means a threshold was crossed. Try these:

    • Raise reads per write to 100. Writes stop mattering, while the cache grows.
    • Set bytes per write to 2 MB (a photo). Storage jumps to thousands of petabytes.
    • Drop daily users to 1 million. Every row says one node.

    It divides by the exact 86,400, so its rates run about 15% above the text’s.

    The comments service: change an assumption
    Requests, average
    23,000/s
    Requests, peak
    69,000/s
    Writes, peak
    6,300/s
    One relational primary takes this.
    Reads, peak
    63,000/s
    More than a few replicas comfortably serve: put a cache in front.
    Storage over the plan, all copies
    500 TB
    Past a few TB per copy: partition the data, or archive the cold part.
    Egress bandwidth, peak
    690 MB/s
    Under one 10 Gbps NIC. Not a design driver.
    Cache memory (upper bound)
    180 GB
    More than one node holds: shard the cache.
    App servers at peak
    35
    App servers with one zone of three down
    53
    Losing a zone leaves two thirds of the fleet, so run 1.5 times the peak need.

    The same chain as code. Each line uses only earlier lines, so a wrong output traces to one assumption.

    Capacity.javaassumptions.pyCapacity.csassumptions.goassumptions.ts
    import java.math.BigDecimal;
    import java.math.MathContext;
    import java.util.List;
    import java.util.Map;
    record Assumptions(
    double dailyUsers,
    double requestsPerUser, // a day
    double readsPerWrite,
    double peakFactor, // peak hour over the daily average
    double bytesPerWrite, // row plus indexes, before replication
    double years,
    int copies, // replication factor
    double bytesPerResponse,
    double qpsPerServer, // measured at the utilization you plan to run at
    double hotShare) {} // the 80/20 rule: cache a fifth of a day's reads
    final class Capacity {
    // Code can afford the exact value. In your head, round it to 10^5.
    static final double SECONDS_PER_DAY = 86_400;
    static final double DAYS_PER_YEAR = 365;
    // Two significant figures: the third never changes a design, and it reads as false precision.
    static String sig2(double n) {
    if (n <= 0) return "0";
    return new BigDecimal(n).round(new MathContext(2)).stripTrailingZeros().toPlainString();
    }
    static String count(double n) {
    double[] sizes = {1e12, 1e9, 1e6, 1e3};
    String[] words = {"T", "B", "M", "k"};
    for (int i = 0; i < sizes.length; i++) if (n >= sizes[i]) return sig2(n / sizes[i]) + words[i];
    return sig2(n);
    }
    // Decimal units (1 KB = 1,000 bytes), as disks, networks and cloud bills use.
    static String size(double n) {
    String[] units = {"B", "KB", "MB", "GB", "TB", "PB", "EB"};
    int i = 0;
    while (n >= 1000 && i < units.length - 1) {
    n /= 1000;
    i++;
    }
    return sig2(n) + " " + units[i];
    }
    static List<Map.Entry<String, String>> estimate(Assumptions a) {
    // Each step uses only the line before it, so a wrong assumption is easy to trace.
    double avg = a.dailyUsers() * a.requestsPerUser() / SECONDS_PER_DAY;
    double peak = avg * a.peakFactor();
    double writeShare = 1 / (a.readsPerWrite() + 1);
    double writesPerDay = avg * writeShare * SECONDS_PER_DAY;
    double storage = writesPerDay * DAYS_PER_YEAR * a.years() * a.bytesPerWrite() * a.copies();
    // Upper bound: many of a day's reads hit the same item, so the distinct hot set is smaller.
    double cache = (1 - writeShare) * avg * SECONDS_PER_DAY * a.hotShare() * a.bytesPerWrite();
    long servers = (long) Math.ceil(peak / a.qpsPerServer());
    return List.of(
    Map.entry("requests/s, average", count(avg)),
    Map.entry("requests/s, peak", count(peak)),
    Map.entry("writes/s, peak", count(peak * writeShare)),
    Map.entry("storage, all copies", size(storage)),
    Map.entry("egress at peak", size(peak * a.bytesPerResponse()) + "/s"),
    Map.entry("cache, upper bound", size(cache)),
    // Three zones: losing one leaves two thirds of the fleet, so run 1.5 times the need.
    Map.entry("app servers", servers + ", " + (long) Math.ceil(servers * 1.5) + " with a zone down"));
    }
    }
    class Main {
    public static void main(String[] args) {
    var comments = new Assumptions(100e6, 20, 10, 3, 500, 5, 3, 10_000, 2_000, 0.2);
    for (var line : Capacity.estimate(comments))
    System.out.printf("%-21s%s%n", line.getKey(), line.getValue());
    // requests/s, average 23k
    // requests/s, peak 69k
    // writes/s, peak 6.3k
    // storage, all copies 500 TB
    // egress at peak 690 MB/s
    // cache, upper bound 180 GB
    // app servers 35, 53 with a zone down
    }
    }

    Worked example 1: URL shortener, where reads and one hot key decide

    Section titled “Worked example 1: URL shortener, where reads and one hot key decide”

    From the URL shortener’s capacity estimates:

    writes: 100 million links a month ÷ 2.6 million s ≈ 40 a second, 400 at a bursty peak
    reads: 100 redirects per link → 4,000 a second, 40,000 at a viral peak
    IDs: 1.2 billion a year × 10 years = 12 billion → 7 Base62 characters (3.5 trillion codes)
    storage: 12 billion × 500 bytes = 6 TB over 10 years
    cache: 350 million redirects a day × 20% × 500 bytes ≈ 35 GB
    egress: about 2 MB/s of redirect headers

    What each number decided:

    • One relational primary, for 40 writes a second.
    • A cache for 40,000 reads, with a plan for one viral code.
    • One database node for 6 TB, partitioned in year two or three.
    • One cache node for 35 GB.

    Bandwidth is ignored, and saying so is part of the answer.

    Worked example 2: News feed, where the estimate makes the central decision

    Section titled “Worked example 2: News feed, where the estimate makes the central decision”

    From the news feed’s capacity estimates:

    feed loads: 500 million users × 10 loads = 5 billion a day ≈ 58,000 a second, 170,000 at peak
    posts: 0.2 per user per day = 100 million a day ≈ 1,200 a second, 3,500 at peak
    followers: 200 on average
    pull: 170,000 loads × 200 authors = about 35 million lookups a second at peak
    push: 100 million posts × 200 followers = 20 billion inserts a day ≈ 690,000 a second at peak
    timelines: 500 entries × 30 bytes × 1 billion users active in 30 days ≈ 15 TB

    The feed’s central question is fan-out on write or on read. You answer it by putting both in one unit: operations a second at peak. 690,000 small writes beat 35 million reads.

    Then the average of 200 followers turns out to hide a power law. One account with 50 million followers is 50 million inserts in a burst. That leads to the hybrid: pull for the largest accounts, and no pushes to inactive followers. That brings push to about 290,000 inserts a second. 15 TB of timelines (30 TB with a replica) means about 300 cache nodes.

    Worked example 3: Instagram, where bytes matter more than requests

    Section titled “Worked example 3: Instagram, where bytes matter more than requests”

    From Instagram’s capacity estimates:

    views: 500 million users × 200 items a day ≈ 1.2 million a second, 3.5 million at peak
    uploads: 300 million items a day ≈ 3,500 a second, 10,000 at peak, a quarter video
    ingest: 10,000 a second × (2 MB photos and 10 MB videos) ≈ 42 GB/s at peak
    egress: 3.5 million views × 400 KB ≈ 1.4 TB/s ≈ 11 Tbps at peak
    storage: about 700 TB of new feed media a day → 1.3 EB over five years before replication
    transcode: 75 million videos × 20 s × 8 core-seconds per second ≈ 140,000 cores busy

    Requests alone suggest a large but ordinary web service. Bytes change everything:

    • 42 GB/s of ingest sends uploads straight to object storage.
    • 1.4 TB/s of egress means media comes only from a CDN, with rendition size and hit ratio as cost decisions.
    • 1.3 EB means tiered storage.
    • 140,000 cores give transcoding its own queue and fleet.

    Across the three: the URL shortener is decided by request rates, the news feed by operations per request times fan-out, and Instagram by bytes. Picking which of those to estimate first is the judgment the next section is about.

    Of a dozen numbers that could be estimated, four or five matter: the ones the hardest requirement depends on.

    Number Estimate it first when Example
    Request rate, read and write Always; it decides caches, replicas, partitioning URL shortener, rate limiter
    Operations per request, fan-out One request triggers many reads or writes News feed (200 followers), chat (4 deliveries per message)
    Storage and its growth Data is kept for years, or is media Instagram, metrics, file sync
    Bandwidth Payloads are large: media, files, replication streams Video streaming, message queue (24 GB/s of broker traffic)
    Memory for state The hot path needs everything in RAM Leaderboard, typeahead trie, top-k sketches, rate limiter
    Concurrent connections Clients hold sockets open Chat, collaborative editor, ride hailing
    Compute Each item needs heavy processing Video transcoding, ML inference
    Money Errors or egress cost real dollars Ad clicks ($500,000 a day per 0.1% error), video CDN
    Approach How Wins when Weakness
    Top-down from users Users × actions × size, as on this page A new product or an interview: demand is the unknown Every factor is a guess, and errors multiply
    Bottom-up from capacity What one node handles, times nodes you can afford or operate A fixed budget or existing fleet: “how much load can 40 brokers take?” Says nothing about whether demand will reach it
    From a known system Scale a measured system by a ratio (“like our checkout, × 5”) An existing company with metrics Inherits the old system’s inefficiencies as facts

    Top-down is the default. Bottom-up is the check that turns 60,000 requests a second into 3 machines, or 3,000.

    Plan for When it is right What it costs
    Average Batch work that can queue: nightly jobs, transcoding backlogs, analytics Work waits during the peak; must be acceptable to the product
    Peak hour User-facing request paths Idle capacity off-peak, partly recovered with autoscaling
    Peak plus a zone down Anything with an availability target above about 99.9% About 1.5 times the peak fleet, idle most of the time
    A predicted spike Scheduled events: on-sales, launches, broadcasts Pre-scaling, or a queue that admits at a fixed rate instead
    Go deeperBinary or decimal units, and when the difference shows1 min

    Disks, networks and cloud bills use decimal units: 1 KB = 1,000 bytes, 1 TB = 10^12 bytes. Memory and many operating system tools use binary ones: 1 KiB = 1,024 bytes, 1 TiB = 2^40 bytes. The gap grows with each step: 2.4% at kilo, 4.9% at mega, 7.4% at giga, 10% at tera, 12.6% at peta. That is why a “1 TB” disk shows as about 931 GiB.

    For estimation, the difference never changes a decision. Pick decimal, because the numbers on the bill are decimal, and powers of ten make the arithmetic easier. Never mix the two in one chain.

    Estimates fail silently, by putting the design in the wrong row. The cost shows up months later as an outage or a bill.

    Mistake What happens How to catch it Fix
    Bits and bytes confused Bandwidth off by 8×; a 10 Gbps NIC treated as 10 GB/s Units written on every line Convert once, at the end, with × 8 or ÷ 8
    Per day treated as per second, or reverse Off by 10^5 The answer exceeds Google search, or rounds to zero Keep “/s” and “/day” on every number
    Average used where peak matters Fleet falls over every evening No peak factor anywhere in the working Multiply by 2 to 3 for the daily curve, more for events
    The mean hides a power law Averages fit, but one celebrity, one viral key or one big tenant breaks a shard Ask “what is the largest one?” next to every average Design the hot case separately: hybrid fan-out, hot-key replication
    Requests counted, bytes ignored Web tier sized right, network and storage off by 100× Any payload above about 100 KB Estimate bytes a second and bytes stored next to request rates
    Copies and overhead forgotten Storage off by 3 to 10× (replicas, indexes, backups, headroom) Storage equals raw payload × count Multiply in copies, index overhead and a 70% fill target

    Each line is approximate. What matters is which side a number falls on, by a wide margin.

    Quantity Below this, one of something is fine Above it, the design changes to
    Writes a second About 5,000 to 10,000 Partitioning, or a store built to spread writes across nodes
    Reads a second from a database About 10,000 to 50,000 A cache in front, then more replicas
    Reads a second from one cache node About 100,000 A sharded cache cluster, an in-process cache for the hottest keys
    Data size in one SQL database A few TB Partitioning, or archiving cold data
    Hot set in memory About 100 GB A sharded cache
    Egress About 1 GB/s (10 Gbps) Many servers, then a CDN
    Open connections per box About 100,000 to 300,000 A dedicated connection tier and a registry of who is where
    Total data About 1 PB Object storage, tiering, and cost as the main design driver
    Latency budget About 100 ms for a user action No sequential cross-region calls; data near users

    Running the comments service at 10 times the users: 600,000 requests a second at peak, 55,000 writes a second, 5.5 PB over five years. Writes are past one primary, so the store must be partitioned. The cache is now about 1.8 TB, around 20 nodes. Storage crosses into petabytes, so old comments move to cheaper storage. Egress is 6 GB/s, still fine spread over 450 servers.

    At 100 times: 6 million requests a second from a global audience that cannot all reach one region inside the latency budget. The design becomes multi-region, which brings in replication across regions and consistency choices that a single-region design never had to make.

    Each factor of ten crosses a few thresholds, not all of them. Rerunning the chain at 10× and 100× shows which component breaks next.

    Go deeperTurning estimates into a capacity plan, with prices1 min

    An estimate is a hypothesis. Production replaces it with measurements:

    • Load test one node with a realistic request mix to replace the per-node guess with a measured number at the target latency.
    • Track the inputs, not just the outputs. Daily users, actions per user, bytes per record and peak-to-average ratio, each as a dashboard. When an input drifts, rerun the chain.
    • Keep headroom of 30 to 50% above the forecast peak. Alert on utilization trends weeks before the line crosses, since buying hardware or raising cloud quotas takes time.
    • Put money next to capacity. Storage and egress are priced per GB. At AWS list prices in us-east-1, S3 Standard is about $0.023 per GB-month and internet egress starts around $0.09 per GB. The comments service’s 550 TB is about $13,000 a month in object storage, and about $44,000 on block storage at $0.08 per GB-month. Its 600 MB/s of peak egress, averaged over a month, is around 500 TB, roughly $25,000 to $45,000 a month at volume tiers. The video streaming problem’s estimate ends at $160 million a month of CDN egress, which is why its design is mostly about bytes.
    Go deeperQueueing in one paragraph: why 70% utilization is a planning target1 min

    Take a single server with random arrivals and service times (the M/M/1 queue). The average time in the system is the service time divided by (1 − ρ), where ρ is utilization. At ρ = 0.5, a request takes twice its service time. At 0.8 it’s five times, at 0.9 ten times, and at 0.95 twenty times.

    Real servers with many cores do better than one queue, but the shape is the same. The curve is flat until around 60 to 70%, and then turns up sharply. Sizing to 50 to 70% at peak keeps the fleet on the flat part. It also leaves room for a lost zone or a retry storm, without falling off the steep part.

    Interviewer asksWe have 50 million daily users. Roughly how many requests a second is that?

    It depends on what each user does, so I will assume about 20 requests a user a day. That’s a few app opens, each firing several API calls. That is a billion requests a day. With about 10^5 seconds in a day, it’s roughly 10,000 a second on average. Evenings run 2 to 3 times the average, so I would plan for 30,000 a second at peak. Say most of that is reads, at 10 to 1. Then writes are under 3,000 a second, which one relational primary handles. Reads, at about 27,000, want a cache in front of the database.

    Interviewer asksHow much storage will this need in five years?

    New records a day, times bytes per record, times days kept, times copies. Say 200 million new comments a day, at about 500 bytes each, including IDs, timestamps and index entries. That’s 100 GB a day. Five years is about 1,800 days, so 180 TB. With three replicas, it’s about 550 TB. I would plan disks at about 70% full, so around 800 TB provisioned. That is far past the few TB one database node holds comfortably. So the data must be partitioned, unless old comments can move to object storage after a year.

    Interviewer asksYou estimated 35 GB for the cache. So what?

    So the hot set fits in one cache node’s 100 GB, with room to triple. There’s no cache sharding on day one: one node plus a replica. The real cache problem is the one hot key. At 2 TB, the decision would flip to a sharded cluster with consistent hashing. And I would question whether 20% of daily reads is the true hot set, since distinct items are fewer than requests.

    Every worked problem on this site opens with an estimate built this way. The deciding numbers in a few:

    • URL shortener, news feed and Instagram: the three worked examples above, decided by request rates, fan-out and bytes.
    • Chat: 700,000 sends a second at peak and 200 million open sockets, so a partitioned store and a dedicated connection fleet.
    • Video streaming: 50 Tbps and 8.1 EB a month of delivery, an estimate that ends in money.
    • Typeahead: keystrokes multiply searches into 210,000 requests a second and a 10 ms server budget.
    • Stock exchange: 430,000 messages a second, against a million per thread. So one matching thread could carry the market at 43% busy. Storage does not matter.
    • Ad click aggregator: 58,000 clicks a second, and $500,000 a day per 0.1% error, so correctness is the design driver.
    • Payment system: 600 payments a second at peak, small enough that correctness, not scale, shapes the design.

    The job. Four or five numbers that pick an architecture, each ending in a decision.

    Numbers to know.

    • A day is about 10^5 seconds. 1 million a day is about 12 a second. 2^10 ≈ 10^3.
    • Memory 100 ns, NVMe 100 µs. A same-zone round trip is 0.25 ms, and cross-zone 1 ms. Across an ocean it’s 70 to 150 ms, and the far side of the world about 250 ms.
    • Per node, as orders of magnitude: an API server does a few thousand requests/s, and a SQL primary about 10,000 writes/s. A Redis shard does 100,000+ ops/s. A NIC is 10 to 25 Gbps. A cache node holds about 100 GB.

    The chain. Users × actions ÷ 10^5 = average per second. × 2 to 3 for the daily peak, more for events. Split by read to write ratio. Writes × bytes × days × copies = storage. Peak × response size × 8 = bits a second. 20% of a day’s reads × item size = cache upper bound. Peak ÷ per-server rate, × 1.5 for a lost zone = servers.

    Checks and stopping. One or two significant figures, units on every number. Divide back per user, compare with a public system and with one machine. Stop when every number is clearly on one side of a threshold.

    Where it goes wrong. Bits for bytes, per day for per second, average for peak, a mean hiding a power law, bytes ignored, copies forgotten.