System Design

2) Performance math & sizing — detailed guide

A reusable sizing template for any system design interview, plus a running example: Facebook-like Home Feed (read-heavy feed math, cache hits, and latency budgets).

0) How to use performance math in interviews

Say
“I’ll do quick, defensible math to pick the right architecture: latency budget, peak QPS, cache hit target, headroom, and a rough cost sketch.”
Checklist
Template
  • Start with 3 anchors: peak QPS, payload size (p50/p95), and latency SLO (p95/p99).
    Most sizing mistakes come from using averages. Use peak with a multiplier, and speak in percentiles (p95/p99).
  • Convert users → actions → QPS: DAU × actions/day ÷ 86,400 → avg; then apply peak multiplier.
    If you’re missing numbers, make reasonable assumptions and say them out loud. The reasoning matters more than precision.
  • Use Little’s Law: concurrency = RPS × latency (seconds) to size pools and in-flight limits.
    This is the fastest way to estimate how many requests are in flight and whether pools/queues are safe at peak.
  • Turn cache hit into DB load: origin QPS = QPS × (1 − hit).
    A 90% cache hit reduces DB by 10×. This single line often justifies introducing Redis/Memcached.
  • Always include headroom: size for peak × (1.3–2.0) and keep utilization under the knee.
    As utilization approaches 1, queueing delay explodes. Keep ρ ≤ ~0.6–0.7 for latency-sensitive paths.
Facebook-like Home Feed — baseline assumptions
Example
  • DAU: 10M; feed opens/user/day: 10 → 100M feed reads/day
    Avg ≈ 1,157 RPS; peak (×8) ≈ 9,259 RPS.
  • SLO: GET /feed p95 ≤ 250ms (server-side)
    We will budget latency hop-by-hop and keep retries/hedging within this envelope.
  • Payload: 25 items/page, ~800B/item → ~20KB/page (metadata only)
    Media bytes are served via CDN/object store; the feed API returns metadata + URLs.
  • Cache hit target: 90% for the feed head
    DB sees ~926 QPS at peak on misses.

A) Latency & throughput basics; p50 / p95 / p99 thinking

Say
“Latency is per-request time; throughput is requests per second. I’ll reason in percentiles and set a hop-by-hop budget.”
Checklist
Template
  • Define SLO in percentiles: p95/p99 latency target + error/availability target for the critical endpoint.
    Percentiles matter because tail latency drives user pain. Pick the handful of endpoints that matter most.
  • Budget hop-by-hop: LB/edge → auth → service → cache → DB → serdes/network.
    Always keep a buffer for tail risk. If you spend your entire budget on ‘expected’ work, p95 will miss.
  • Tail amplifies with fan-out: overall latency trends toward the slowest subcall.
    This is why we batch and parallelize carefully, and why we cap fan-out in the read path.
  • Tail mitigation: per-hop timeouts, bounded retries + jitter, hedged reads for idempotent reads, bulkheads.
    Retries can worsen tail if unbounded. Hedging is a controlled way to cut p99 when replicas are independent.
Home Feed — SLO & budget (example)
Example
  • SLO: GET /feed p95 ≤ 250ms (server)
    We keep the read path fast using cache hits; slow dependencies trigger fallback to last-good cached pages.
  • Budget split: Edge/LB 10ms + Auth 15ms + FeedReadSvc 15ms + Redis 10ms + DB 50ms + serdes/net 25ms + buffer 125ms = 250ms
    If DB p95 rises, the buffer gets eaten first. That’s your early signal to scale cache, reduce misses, or shard.
Optional: speakable ‘budget line’
Example
“We’ll target p95 250ms for feed reads. I’ll budget it across hops and keep ~50% as buffer for tail risk, so we can survive spikes without missing SLO.”

B) Little’s Law (L = λW), utilization, and queueing intuition

Say
“I’ll estimate concurrency with Little’s Law and keep utilization below the knee so tails don’t explode.”
Checklist
Template
  • Little’s Law: L = λ × W — in-flight concurrency = RPS × avg time in system.
    Use this to size thread pools, connection pools, and max in-flight requests at peak.
  • Utilization: ρ = λ / μ. As ρ → 1, queueing delay grows superlinearly.
    You don’t need exact queueing math—just explain the knee and why headroom is mandatory.
  • Rule of thumb: keep ρ ≤ 0.6–0.7 at peak for latency-sensitive services.
    Higher utilization may be fine for offline/batch; it’s dangerous for interactive APIs like feeds.
Home Feed — concurrency & knee (example)
Example
  • Concurrency: peak λ≈9,259 RPS and W≈120ms (0.12s) → L≈ 1,111 in-flight
    That’s the number that should guide max in-flight limits and pool sizing. If your pools are smaller, you’ll see queueing and p95 spikes.
  • Knee intuition: If a DB node sustains μ=2000 QPS at S=50ms, then ρ=0.6 is healthy; ρ=0.85 produces big tail latency.
    This is why feed systems keep DB protected with caches and avoid saturating it during traffic bursts.

C) Estimate: read/write QPS, fan-out, payload sizes, cache hit ratio

Say
“I’ll compute peak QPS, then apply cache-hit and fan-out to see the real load on DB, egress, and workers.”
Checklist
Template
  • Traffic sizing: DAU/MAU × actions/user → avg RPS; apply peak multiplier (×4–×10).
    Use peak to select storage/caches; use average mainly for cost intuition.
  • Fan-out math: backend QPS = front-door QPS × fan-out × (1 − cache_hit) per layer.
    Identify where fan-out happens (sync read path vs async pipelines) and ensure the read path stays bounded.
  • Payload sizing: use p50/p95 sizes; use pagination, compression, and CDNs.
    Separate metadata payload from media bytes. Many feed systems return IDs + minimal metadata and hydrate in batch.
  • Cache hit target H: origin QPS = QPS × (1 − H); prevent stampede via coalescing + jittered TTL.
    Cache hit drives DB cost and latency. Mention stale-while-revalidate and request coalescing for hot keys.
Home Feed — peak QPS, DB load, and egress (example)
Example
  • Peak feed reads: ~9,259 RPS
    Derived from DAU and opens/day. Peak multiplier accounts for diurnal + bursts.
  • Cache hit: 90% → DB sees ~926 QPS
    This single line shows why Redis matters: 90% hit makes DB 10× smaller and keeps tails under control.
  • Payload: ~20KB per page (metadata only) → peak metadata egress ~177 MB/s
    Real egress is dominated by media bytes, so use CDN for images/videos and keep API responses small and cacheable where possible.
  • Hydration: batch-get posts by postIds to avoid N+1 calls
    Even if each page has 25 items, don’t do 25 RPCs. Do 1–2 batch calls and cache hydrated post summaries.

D) Capacity headroom, peak/diurnal traffic, burst handling

Say
“I’ll size for peak with headroom and describe the overload behavior (rate-limit, queue, shed).”
Checklist
Template
  • Headroom policy: size for peak × 1.3–2.0; keep ρ ≤ 60–70% at peak.
    Headroom covers failure (AZ loss), deployments, and randomness in tail latency.
  • Bursts: queues between tiers; autoscale on lag/latency; shed non-critical work; early 429/503 with Retry-After.
    Prefer fast failures over slow timeouts. Protect DB first with pool caps, backpressure, and circuit breakers.
  • Diurnal: run batch/compaction off-peak; plan for event spikes.
    If the workload has a daily peak, schedule heavy background jobs away from it.
Home Feed — quick instance sizing sketch (example)
Example
  • Provisioned target: peak × 1.5 = 13,889 RPS
    This includes headroom for spikes and partial failure.
  • If one API instance sustains: 400 RPS at ~60% utilization → need ~35 instances
    Then add N+1/AZ and room for deploys. Exact numbers depend on CPU cost of ranking/hydration.
  • Burst plan: edge token buckets + brownout mode (fall back to cached/recency feed), autoscale workers on queue lag.
    If ranking pipeline is unhealthy, degrade to recency to keep availability and latency SLOs.

E) Cost rough-cut (compute, egress, storage, ops)

Say
“I’ll sketch costs at a high level and call out the biggest levers.”
Checklist
Template
  • Compute: instances = count × $/hr × 730 (include spare/LB/NAT). Serverless = requests + duration.
    Give relative drivers rather than exact dollars. Mention you’ll validate with real pricing later.
  • Egress: GB egressed × $/GB; CDN can reduce origin egress dramatically.
    For feeds, media egress usually dominates. CDN caching and compression are the big levers.
  • Storage: GB-month across hot/warm/cold tiers; include IO/requests; lifecycle old data.
    Feeds and posts grow fast. Use TTL/lifecycle and keep indexes lean.
  • Ops/observability: logs/metrics/traces (GB/day), retention policies, sampling.
    Sampling and retention are cost controls. Also avoid logging PII and large payloads.
Home Feed — cost levers (example)
Example
  • Biggest costs: CDN/media egress, cache tier, and DB reads (if cache hit is low).
    Keeping cache hit high reduces both DB cost and tail latency.
  • Largest savings: smaller payloads, better cache hit, aggressive CDN for media, and log sampling.
    Return metadata + URLs (not media). Compress responses. Use lifecycle policies for older content and logs.
Quick line items you can say
Template
Compute ≈ instance_count × $/hr × 730
Storage ≈ GB × $/GB-month (+ IO/requests)
Egress ≈ GB_out × $/GB (CDN reduces origin)
Observability ≈ GB/day × $/GB (retention + sampling matters)

F) Mini worked example (tie it all together)

Say
“Now I’ll run the full template end-to-end using the Home Feed assumptions.”
Home Feed — end-to-end sizing narrative
Example
Problem: Read-heavy Facebook-like Home Feed (metadata response; media via CDN). Inputs: - DAU: 10M - Feed opens/user/day: 10 - Reads/day: 100M → avg ~1,157 RPS - Peak multiplier: ×8 → peak ~9,259 RPS - SLO: feed read p95 ≤ 250 ms - Cache hit target: 90% - Feed skeleton payload: ~20KB/page 1) Latency budget Edge/LB 10, Auth 15, Service 15, Redis 10, DB 50, net/serdes 25, buffer 125 → 250 ms. Hedged reads after ~120 ms to a second replica (idempotent reads only). 2) Concurrency (Little’s Law) At peak λ=9,259 RPS and W≈0.12s: L ≈ 1,111 in-flight. Make sure pools, max-in-flight, and autoscale policies cover this with headroom. 3) Cache → DB protection DB QPS ≈ peak × (1−H) = 9,259 × 0.10 ≈ 926 QPS. Protect hot keys with request coalescing + staggered TTLs. 4) API fleet sizing (rough) Provision target: peak × 1.5 = 13,889 RPS. If one instance safely handles 400 RPS at target utilization: Need ≈ 35 instances + N+1/AZ + deploy room. 5) Egress intuition (metadata only) Peak metadata egress ≈ 177 MB/s. Media egress is much bigger → CDN is mandatory. 6) Burst plan Edge rate limits + autoscale on latency/queue lag. Brownout: if ranking is slow, serve cached/recency feed. Protect DB with pool caps and circuit breakers (fast fail over slow timeouts).

G) Quick formulas & rules you can quote

Say
“Here are the short formulas you can quote during sizing.”
Checklist
Template
  • Little’s Law: L = λW (concurrency = RPS × latency)
    Use for pools, in-flight, worker counts.
  • Utilization: ρ = λ/μ; keep ≤ 0.6–0.7 at peak
    Avoid the knee where queues explode and tails spike.
  • M/M/1 intuition: R ≈ S / (1 − ρ)
    Not exact in real systems, but great for explaining why headroom matters.
  • Cache: QPS_origin = QPS × (1 − H)
    Hit rate is the biggest lever for DB load and tail latency.
  • Peak planning: peak = avg × multiplier (×4–×10)
    Use peak for sizing, avg for cost intuition.
  • Retry budget: retries must fit inside SLO
    Use bounded retries + jitter; idempotency keys for writes.
Speakable mini-cheat sheet
Template
avg_RPS = actions_per_day / 86,400
peak_RPS = avg_RPS × peak_multiplier
concurrency ≈ peak_RPS × latency_seconds
origin_QPS = peak_RPS × (1 − cache_hit)
keep utilization below ~70% at peak (tails explode near saturation)