AI EngineeringZero to ProductionHome·About·What’s new·Contact
Career & Interview Prep · Chapter CR4

System-design interview

The System Design method, out loud in 45 minutes: requirements→estimation→API→data→architecture→scale, deep-diving a bottleneck with tradeoffs — and the senior-vs-staff signals.

⏱️ ~2 hours🧪 2 labs🎯 Intermediate→Tech-lead

Learning objectives

  • Drive a system-design interview with a repeatable method.
  • Do capacity estimation out loud.
  • Cover API, data model, architecture, and scale.
  • Hit the seniority signals (senior vs staff).
📋 Before you startThis page builds on: HLD: architecture & caching · Scalability & CAP. Jumping in? Skim those first — or open the recap.
30-second recap
  • HLD: architecture & caching: The standard web shape: load balancer → stateless services → cache → database, with caching as the biggest performance lever.
  • Scalability & CAP: Scale up (bigger machine) or out (more machines); replicas trade consistency for availability, and CAP says you can't have both during a partition.
▶ Runnable companionThe tools here are saved under code/cr4-systemdesign-interview/ — run them against your own resume, stories, and offers.

1 · The method (you already have it) essential

Picture the failure mode, because you've probably watched it happen. A strong engineer gets "Design Twitter," goes quiet for ten seconds, then dives straight into database schemas. Twenty minutes later they've drawn a beautiful data model — and never asked how many users, never estimated the load, never mentioned the read/write skew that should have driven the whole thing. They knew every component cold and still failed the interview, because a system-design interview isn't a knowledge test. It's a process test: can you take a deliberately vague prompt and drive it to a defensible design under time pressure, thinking out loud the entire way?

That reframe is the single most important thing on this page. Think of the interviewer less as an examiner and more as a skeptical staff engineer you've been paired with for 45 minutes to whiteboard a system. They can't see inside your head — they can only grade what you say and draw. So the method isn't a checklist to recite; it's a way to make your reasoning visible and keep the conversation moving instead of stalling. The five steps below — requirements, estimate, API, data model, architecture — are just the natural order a good engineer would actually work in: figure out what you're building, how big it is, its interface, its data, then its shape.

Why does the order matter so much? Because each step feeds the next, and skipping one leaves the later ones ungrounded. You can't size storage before you know the retention window (a requirement). You can't pick "add a cache" convincingly until your estimate shows 40k reads/second. The classic mistake — and the fastest way to read as junior — is jumping to the fun part (architecture boxes) before the boring parts (scope and numbers) have earned you the right to draw them. The requirements and estimation steps feel slow, but they're what make every downstream choice defensible instead of arbitrary. Drive the sequence, narrate as you go, and manage the clock — roughly five minutes clarifying, five estimating, then the bulk on design with time reserved to deep-dive. The capstone trained the reasoning; this section is about performing it live.

drive left → right; each step grounds the next, and you narrate the whole way 1 ·Requirements functional + not 2 ·Estimate QPS · storage 3 ·API the endpoints 4 ·Data model + shard key 5 ·Architecture scale bottleneck skip an early step and every later one is ungrounded It's a process test, not a knowledge test. The five steps run in a fixed order because each one earns the next — you can't size storage before the retention requirement, or justify a cache before the estimate shows the read load.
🗺️ How to read this diagram

Read the boxes left to right — that is the exact order you drive the interview, and the blue arrows show each step handing its output to the next.

  • The blue boxes 1–4 are the "boring" groundwork: what you're building (requirements), how big it is (estimate), its interface (API), and its data (data model + shard key). Boxes 2, 3 and 4 each consume what the box before it produced.
  • The green box 5 is the payoff — the architecture you actually draw — and its label reminds you the last move is to scale the bottleneck your estimate exposed.
  • The dashed curved arrow underneath is the trap: jump straight to box 5 and skip the early steps, and every design choice reads as arbitrary rather than earned.

In short: the order is the answer — narrate steps 1→5 out loud, and each number and requirement makes the next box defensible.

The system-design interview flow

  1. Requirements: functional + non-functional (scale, latency, consistency). Clarify first.
  2. Estimate: users, QPS, storage — back-of-envelope (SD6).
  3. API: the handful of endpoints.
  4. Data model + shard key (SD2/SD7).
  5. Architecture: client→LB→service→cache/DB (SD5); then scale the bottleneck.

2 · Estimation out loud essential

Here's the moment that separates candidates. The interviewer asks "how would you scale this?" and one candidate says "I'd add caching and sharding" — reasonable-sounding, but pulled from thin air. The other says "let me size it first: ten million daily users, ten actions each, so about 1,200 requests a second average, call it 3,500 at peak, and it's read-heavy so maybe 3,200 of those are reads — that's why I want a cache in front." The second answer isn't smarter. It's just grounded. Every design choice now points back to a number, and the interviewer can see you decide rather than guess.

Estimation intimidates people because it sounds like it demands precision or memorized constants. It demands neither. Think of it like a builder eyeballing a room before ordering materials — nobody expects the estimate to be exact, they expect it to be in the right ballpark and derived from stated assumptions. The whole game is orders of magnitude: is this 100 requests a second or 100,000? That difference changes your entire architecture; the difference between 3,400 and 3,600 changes nothing. So round aggressively, say your assumptions out loud ("assume 10 actions per user per day"), and let anyone challenge them — a challenged assumption you can defend reads far better than a suspiciously precise number you can't.

The mechanics are a short, repeatable chain, and it's worth internalizing because it's the same every time. Start from daily active users and actions each, divide by 86,400 (seconds in a day) to get average QPS. Multiply by a peak factor — traffic isn't flat, it clusters around evenings and events, so 3× to 10× the average is typical — to get peak QPS, which is what you must actually provision for. Then split by the read/write ratio, because reads and writes scale with completely different tools (replicas and caches absorb reads; sharding and queues absorb writes). A couple of useful anchors to keep in your head: there are ~86,400 seconds in a day and ~2.5 million in a month; a "byte-size a record" habit turns counts into storage. The critical discipline is the last one: after each number, say what it implies. "40k reads/second — that demands a cache." "3TB total — that fits comfortably in a sharded database." A number with no conclusion is trivia; a number that forces the next decision is engineering.

turn one count into the numbers that force the next decision DAU × actions/day the starting count avg QPS ÷ 86,400 s/day peak QPS × peak factor (3–10) read/write split peak reads (big) → cache · replicas peak writes → shard · queue each number implies a component — say the implication out loud Every number forces the next decision. The chain is the same each time — DAU → average QPS → peak QPS → split by read/write ratio — and reads and writes then scale with completely different tools.
🗺️ How to read this diagram

Follow the blue arrows left to right along the top, then down where peak QPS splits into its two children.

  • The blue starting box is your one raw input: daily active users times actions each. Dividing by the ~86,400 seconds in a day gives average QPS; multiplying by a peak factor of 3–10× gives peak QPS — the number you must actually provision for.
  • The two boxes at the bottom are that peak split by the read/write ratio. The green reads box is much larger (reads usually dominate) and points at the tools that absorb reads — a cache and read replicas. The amber writes box points at sharding and queues, which absorb writes.
  • The payoff is the caption line at the bottom: a number is only useful once you say what it implies — "40k reads/second, so I want a cache."

In short: one count becomes avg → peak → reads/writes, and each split hands you the component to reach for next.

Example code for learning — review, test, and adapt it before running against real or production systems. Commands can create, change, or delete resources. See the Terms & Disclaimer.
Python · capacity estimate you can talk through (runs)
estimate.pydef estimate(dau, actions_per_day, read_write_ratio=10, peak=3):
    avg_qps = dau * actions_per_day / 86_400
    peak_qps = avg_qps * peak
    writes = peak_qps / (read_write_ratio + 1)
    reads = peak_qps - writes
    return {
        "avg_qps": round(avg_qps),
        "peak_qps": round(peak_qps),
        "peak_reads": round(reads),
        "peak_writes": round(writes),
    }

print(estimate(dau=10_000_000, actions_per_day=10))   # a big consumer app
{'avg_qps': 1157, 'peak_qps': 3472, 'peak_reads': 3157, 'peak_writes': 316}
▶ How this works

In a system-design interview you're expected to do quick back-of-the-envelope capacity math out loud — roughly how many requests per second (QPS) your system must handle. This helper does that math so you can see the method: start from daily users, get an average, then a peak, then split into reads and writes.

  1. The inputs (parameters): dau is daily active users, actions_per_day is how many actions each does. read_write_ratio=10 and peak=3 have defaults — a typical app reads about 10× more than it writes, and peak traffic is roughly 3× the average.
  2. avg_qps = dau * actions_per_day / 86_400 spreads the day's total actions over the number of seconds in a day (86,400) to get the average requests per second. The underscores in 86_400 are just digit separators for readability.
  3. peak_qps = avg_qps * peak scales up to the busy period. Then writes = peak_qps / (read_write_ratio + 1) and reads = peak_qps - writes split that peak into the write share and the (much larger) read share.
  4. The function returns a small dictionary of the four rounded numbers. The bottom line calls it for a big consumer app: 10 million users doing 10 actions a day.

What the output means: {'avg_qps': 1157, 'peak_qps': 3472, 'peak_reads': 3157, 'peak_writes': 316} — about 3,500 requests/sec at peak, mostly reads. Those numbers are what justify decisions like "add a read cache" or "use read replicas".

Try this: Change read_write_ratio to 1 (a write-heavy system) and see reads and writes even out. In the interview, narrate each step as you compute it — the method matters more than the exact figure.

3 · Cover the pillars intermediate

Now the part everyone thinks the interview is about — and where it's still easy to trip. You've scoped it, you've sized it, and now you get to draw the system. The temptation is to sketch one impressive component in loving detail and hope the interviewer is dazzled. But a design that's a gorgeous database schema with no API, or a clever caching layer with no story for how data gets written, reads as lopsided — it signals you can go deep on your favorite topic but can't hold a whole system in your head. The pillars exist to stop that: they're the four load-bearing pieces every online system has, and covering all of them (even briefly) proves you see the full picture before you zoom in.

Think of it like an architect presenting a building. Before arguing about the lobby marble, they show the plan: entrances (the API — how requests come in), the rooms and how they're laid out (the data model — what you store and your shard key), and how everything connects and holds weight (the architecture — client → load balancer → service → cache/DB). A client who only ever hears about the marble has no idea if the building will stand. Walk the pillars in that order and draw a box for each as you speak; the drawing keeps you and the interviewer synchronized on the same mental model, and it gives them something concrete to point at when they want to steer.

What turns a box-drawing exercise into a senior answer is that every box is justified by the numbers from step 2, not chosen by reflex. This is where the standard building blocks earn their place: a cache because your estimate showed the read path is hot (from SD5); read replicas to fan out those reads (SD6); sharding with consistent hashing because the write volume or data size exceeds one node (SD7); a message queue to decouple slow or bursty work — analytics, notifications — off the request's hot path (SD7). Naming a component is easy; the signal is saying why this one, here, for these numbers. And resist over-engineering: if your estimate says 40 writes a second, proposing a globally sharded multi-region write path is a red flag, not a strength. Match the machinery to the load you actually computed — that restraint is itself a seniority signal.

walk the pillars: client → load balancer → service → cache/DB, with a queue off the hot path Client request in Load balancer fan out Service app tier · API Cache hot reads · load-bearing Database sharded · replicas Queue async · off path read miss write bursty work Four pillars, then point at the load-bearing one. Every online system is client → load balancer → service → cache/DB; each added box (cache, replicas, shard, queue) is justified by the numbers from step 2, not chosen by reflex.
🗺️ How to read this diagram

Follow a request left to right: it enters at the client and flows through the load balancer into the service, which then talks to the data layer on the right.

  • The solid blue arrows are the request path — client → load balancer → service. The service then does a read against the green cache, and only on a miss (dashed) drops down to the database behind it.
  • The dashed write arrow shows writes going to the database, and the dashed arrow down to the amber queue shows bursty or slow work (analytics, notifications) pulled off the hot path so it can't slow the request.
  • The green cache is drawn as the load-bearing box on purpose: when your estimate says the read path is hot, that is the one component you deep-dive — naming why this box, for these numbers is the senior signal.

In short: cover all four pillars in order, then justify each extra box with a number from your estimate and point at the one carrying the load.

4 · Advanced — deep-dive a bottleneck advanced

There's a predictable pivot around the 25-minute mark, and candidates who don't expect it lose their footing. You've laid out the whole system, the interviewer nods, and then they say "let's go deeper on the cache" — or the sharding, or how the queue guarantees delivery. This is not them poking a hole; it's the most important part of the interview finally starting. Breadth showed you can architect a system. Depth shows whether you've actually operated one, or just memorized the boxes. Someone who has only read about caches can draw a cache; someone who has run one in production knows about invalidation, cold starts, and the thundering herd. The deep-dive is where that difference becomes audible.

Here's the mental shift: breadth is being a tour guide pointing at buildings; depth is being the structural engineer who can tell you exactly how one of them handles a load. When the interviewer picks a component, they hand you the microphone — and the single best move is to steer them toward the bottleneck your estimate already exposed. If your numbers screamed "40k reads a second," you should be eager to deep-dive the read cache, because you've earned the right to and you have specifics ready: the eviction policy, the TTL strategy, what happens on a miss, how you invalidate on writes. Driving the deep-dive toward the component that carries the load — rather than passively answering wherever they point — is a senior signal in itself.

What does "deep" actually mean in practice? It means moving from what to how and what-if. Not "I'd add a cache" but "it's a write-through cache keyed by the short ID, TTL of an hour with jitter so keys don't expire in lockstep, and on a miss I coalesce concurrent requests so one DB read serves them all." Not "I'd shard the database" but "I shard on user ID with consistent hashing, and here's how I handle a celebrity hot key that lands too much traffic on one shard." Concrete numbers, named strategies, and — crucially — the failure cases. Depth on one component with real tradeoffs always beats a shallow tour of ten. If you find yourself listing components again during the deep-dive, you've drifted back to breadth; pull yourself down into the mechanics of the one thing they asked about.

breadth: another shallow tour of boxes depth: open ONE box → how & what-if Cache DB Queue LB Shard Replica named, never opened reads as junior Read cache — the bottleneck how: write-through, keyed by ID how: TTL 1h+jitter · coalesce what-if: dies → thundering herd mechanics + failure case reads as senior Depth beats a second lap of breadth. Re-listing boxes (left) proves you memorized components; opening one box into its how and what-if — TTL, coalescing, the failure mode (right) — proves you've operated one.
🗺️ How to read this diagram

Compare the two halves across the dashed divider: the left is what breadth looks like when the deep-dive starts, the right is what depth looks like.

  • The left grid of blue boxes is the trap — during the deep-dive you keep naming more components (Cache, DB, Queue, LB, Shard, Replica) without ever opening one. It reads as junior because it stops at "does the system have the right parts."
  • The right stack takes the one box your estimate flagged — the read cache (green, the bottleneck) — and drills down: the how rows (write-through, TTL with jitter, request coalescing) and the what-if row in red (the node dies → thundering herd).
  • The blue arrows going down the right side are the move from what → how → what-if; that descent into mechanics and failure is the payoff that reads as senior.

In short: when they say "go deeper," don't relist boxes — open the one bottleneck box and walk its mechanics and its failure case.

Drive, then followLay out the whole design first (breadth), then let the interviewer pull you deep where they want. Candidates who wait to be told what to do read as junior; candidates who drive and adapt read as senior.

5 · Professional — tradeoffs & failure modes professional

Watch what happens when an interviewer hears an answer with no tradeoffs in it. A candidate says "I'll use SQL for strong consistency" and moves on, pleased. The interviewer's face doesn't change, but the score just capped. Not because SQL is wrong — it might be perfect — but because the candidate presented it as a fact rather than a choice. And every real engineering decision is a choice with a cost on the other side. Someone who says "SQL, done" either doesn't see the cost, or is hiding it. Someone who says "SQL, because I need transactions here and I'm willing to accept the write-scaling ceiling that comes with it" shows they see both sides and picked deliberately. That second sentence is the entire difference between a mid-level and a senior answer.

This is the deepest idea on the page, so it's worth stating plainly: in distributed systems there are no right answers, only tradeoffs. The CAP theorem (from SD6) makes it formal — when the network partitions, you must sacrifice either consistency or availability, you cannot keep both — but the principle is everywhere below CAP too. A cache buys read speed and pays with staleness. A queue buys decoupling and pays with eventual consistency and more moving parts. Sharding buys write scale and pays with cross-shard queries and rebalancing pain. The interviewer isn't looking for the option with no downside, because there isn't one. They're looking for whether you can name the downside you're accepting and justify it for this specific system. The tell of true seniority is volunteering the cost before you're asked, and naming the conditions under which you'd flip the choice ("if this were billing data instead of analytics, I'd pay the latency for strong consistency").

The second half of professional-grade reasoning is failure, and it's the half candidates most often skip because the happy path is so much more comfortable to talk about. But production systems spend their interesting moments failing, and interviewers know it. So for every component you draw, keep a reflex question loaded: what happens when this dies? When the cache node fails, do all reads stampede the database (a thundering herd)? When a shard goes down, do you lose that slice of users or fail over? When the queue backs up, do you drop messages or apply backpressure? A design that only describes the happy path is a demo, not a system. The professional move is to name the failure mode precisely — "thundering herd," "fail-open vs fail-closed," "split brain" — and offer layered mitigations rather than a single hopeful fix. Naming failure by its real name signals you've been on call for one.

every choice: what it BUYS (green) ↔ what it PAYS (amber) · and: what if it dies? Cache add for hot reads + read speed buys latency − staleness pays invalidation Queue add to decouple + decoupling buys hot-path speed − eventual consistency pays moving parts Sharding add for write scale + write scale buys throughput − cross-shard queries pays rebalancing failure reflex — when THIS dies, name it:thundering herd · split brain · backpressure There are no right answers, only tradeoffs. Each component you add buys one thing (green) and pays for it with another (amber); the senior move is naming the cost you're accepting — and, in the red band, what happens when the component fails.
🗺️ How to read this diagram

Read each row left to right: the component you'd add, then the benefit it buys (green), then — across the amber arrow — the cost it pays (amber).

  • The blue box on the left of each row is a standard building block: a cache, a queue, sharding. The green box is the upside that made you reach for it, and the amber box is the downside that comes bundled with it — read speed vs staleness, decoupling vs eventual consistency, write scale vs cross-shard pain.
  • The blue arrow is the reason you added the box; the amber arrow is the cost you can't dodge. There's a box on both sides of every choice — that pairing is the whole point.
  • The red band across the bottom is the failure reflex you keep loaded for every component: what happens when this dies? — and the senior move is naming the failure by its real name (thundering herd, split brain, backpressure).

In short: volunteer the amber cost before you're asked, and load the red failure question for every box — that's what reads as senior, not the choice itself.

6 · Tech-lead — the seniority ladder in the room tech-lead

Here's something that surprises people: two candidates can give the exact same design and get different grades. "Design a rate limiter." Both produce a correct token-bucket algorithm backed by a shared counter. One is passed as senior, the other as mid — with identical technical content. How? Because the level you're interviewing for changes the question you're actually answering. The design is the same; what the interviewer is listening for on top of it is not. Understanding this is what lets you aim your effort where it earns credit instead of over-explaining the parts that were already assumed.

The cleanest way to hold it is a ladder where each rung adds a layer instead of replacing one. Mid-level is correct: the right algorithm, the right data structure, the basic distributed case handled, the complexity known. That's a real bar and passing it is not nothing. Senior is correct under failure: everything mid did, plus what happens when the shared counter's Redis dies (fail-open or fail-closed — and that's a business decision, not a technical one), the synchronization overhead of a shared counter, and an algorithm choice defended with reasons. Staff and above is correct for the organization and the business: all of that, plus the product framing (rate-limit per user? per IP? per API key? what's the actual goal — abuse prevention, cost control, fairness?), the cost of running this as shared infrastructure many teams depend on, and how it rolls out safely with observability and tuning. Correct → correct-under-failure → correct-for-the-org. Notice you never abandon the lower rungs; you build on them.

Two practical consequences fall out of this. First, know which rung you're climbing to and reach one notch above comfortable — if you're targeting senior, don't stop at the working design and wait to be asked about failure; volunteer the failure analysis, because volunteering it (rather than being dragged to it) is itself the senior signal. Second, the highest rungs are less about deeper technology and more about widening the frame: from "does the code work" to "does it work when things break" to "is this the right thing to build for the company, and can an org actually operate it." That last move — pulling the conversation up to product goals, cost, and cross-team operability, and genuinely driving the whole discussion rather than answering questions — is what reads as staff. The technology ceiling is real, but the framing ceiling is usually what's actually being tested at the top.

each rung wraps the one below — you never abandon the lower layers Staff · correct for the org & business product framing · cost as shared infra · safe rollout & observability Senior · correct under failure failure modes · fail-open vs fail-closed · tradeoffs defended Mid · correct right algo · data structure · distributed Correct → correct-under-failure → correct-for-the-org. Two candidates can give the same design and grade differently, because the higher rung wraps the lower one with an extra layer — the frame widens, the design doesn't get replaced.
🗺️ How to read this diagram

Read from the inside out — the innermost box is the baseline everyone must clear, and each larger box around it is the next seniority rung adding a layer.

  • The green inner box (Mid) is a correct design: the right algorithm, data structure, and the basic distributed case. That is a real bar, but it stops at "does it work."
  • The amber frame around it (Senior) keeps everything Mid did and adds correct under failure — what happens when a component dies, fail-open vs fail-closed, tradeoffs defended with reasons.
  • The purple outer frame (Staff) wraps both and widens to correct for the org and business — product framing, the cost of running it as shared infrastructure, and safe rollout. Notice the boxes nest, never replace: you build up, you don't swap.

In short: aim one rung above comfortable and volunteer the outer layer — the failure analysis or the product framing — before you're asked.

LevelWhat the design shows
Mida working design with the right components
Seniorjustified tradeoffs, bottleneck deep-dive, failure handling
Staff/Leadambiguity resolved, cost/ops/org impact, drives the whole conversation
You built this muscle alreadyThe System Design track's essential→tech-lead climb is exactly this ladder. In the interview you're demonstrating the tier you operate at — the material trained you to reason at the senior/lead rungs, not just name boxes.

Exercise CR4.1 — Mock a design, out loud

Context: The method only sticks under the clock. Running a full 45-minute mock aloud — clarify, estimate, design, deep-dive a bottleneck — and grading yourself against the seniority table is the rep that counts.

Your task: Pick a prompt (URL shortener, news feed, chat). In 45 minutes and talking aloud: clarify, estimate, sketch API/data/architecture, then deep-dive one component with explicit tradeoffs and a failure mode. Record it and grade yourself against the seniority table.

Requirements:

  • Run the five steps: requirements, estimation, API, data model, architecture
  • Narrate throughout and keep to ~45 minutes
  • Deep-dive one component: name a failure mode and give layered mitigations
  • Make at least one tradeoff explicit and defend it
  • Grade yourself: mid (working design), senior (failure + tradeoffs), staff (org + product framing)

💡 Hint: Pick the bottleneck the estimation exposed and drive the deep-dive there — the numbers should point you at what carries the load.

🪜 Practice ladder beginner → industry

Six graded exercises, easy to real-world. Try each before opening its solution.

Exercise 1 · Clarify before you draw a boxBeginner

Context: Designing before scoping is the most common junior mistake in a system design interview. The first move is clarifying questions that each change a box on the diagram.

Your task: The prompt is "Design a URL shortener." Write the first four clarifying questions you'd ask to pin scope and scale before designing anything, and say why each changes the design.

Requirements:

  • Ask read:write ratio and QPS — changes caching and replication vs ID strategy
  • Ask total URLs and lifetime — sizes the key space and encoding length
  • Ask about expiry and custom aliases — TTL/cleanup and collision checks
  • Ask latency target and consistency needs — how aggressively to cache and async analytics
  • For each, state which part of the design it changes

💡 Hint: A good clarifying question is one whose answer moves a box on the diagram — if it doesn't change the design, it's ritual.

Show solution
  1. “What’s the read:write ratio and expected QPS?” — a 100:1 read-heavy system pushes you toward caching and read replicas; write-heavy changes the ID-generation strategy.
  2. “How many URLs total / over what lifetime?” — sizes the key space and whether 7 vs 8 base-62 characters is enough.
  3. “Do links expire? Custom aliases allowed?” — expiry needs a TTL/cleanup path; custom aliases need a collision check.
  4. “Latency target and consistency needs?” — “redirect in <50ms” and “eventual consistency is fine” let you cache aggressively and go async on analytics.

Designing before scoping is the most common junior mistake. Each question changes a box on the diagram — that’s how you show the interviewer the questions are load-bearing, not ritual.

Exercise 2 · Do the estimation out loudIntermediate

Context: The interviewer wants to hear back-of-envelope math with round numbers and stated assumptions — because the numbers drive the next design decision ("so we need a cache").

Your task: For that URL shortener, estimate storage and QPS from assumptions. Show the back-of-envelope math — round numbers, stated assumptions.

Requirements:

  • State assumptions (e.g. new URLs/month, read:write ratio, retention period)
  • Derive average and peak write QPS
  • Derive average and peak read QPS from the ratio
  • Estimate total storage (record size × record count over retention)
  • Draw a conclusion from each number (e.g. reads demand a cache; storage fits a sharded DB)

💡 Hint: Round aggressively and say the assumptions aloud — the point is that each number forces the next decision, not decimal precision.

Show solution

Assume: 100M new URLs/month, read:write = 100:1, keep 5 years.

  • Writes: 100M / month ≈ 100M / 2.5M s ≈ ~40 writes/s average, call it ~400/s peak (10×).
  • Reads: 100× writes ≈ ~4,000 reads/s average, ~40k/s peak.
  • Storage: ~500 bytes/record (URL + metadata) × 100M/mo × 60 mo ≈ 6B records × 500B ≈ ~3 TB.

Conclusions you state: 3TB fits comfortably in one sharded DB; 40k reads/s demands a cache in front. The point isn’t precision — it’s that the numbers drive the next design decision (“so we need a cache”), spoken aloud.

Exercise 3 · Cover the pillars in one diagramAdvanced

Context: A complete design covers the pillars — API, data model, ID generation, read path, write path — and then names the one component that carries the load, showing you can be thorough and prioritise.

Your task: Sketch (in words) the end-to-end design for the shortener covering the core pillars: API, data model, ID generation, read path, and write path. Name the one component that carries the load.

Requirements:

  • API: a shorten endpoint and a redirect endpoint
  • Data model: id (base-62 PK) → long URL, timestamps, optional TTL
  • ID generation: an encoded counter or Snowflake-style IDs to avoid collision checks
  • Read and write paths distinguished (cache on the read path, ID gen + DB on the write path)
  • Name the cache as the load-bearing component and say why

💡 Hint: Cover every pillar, then point at the one box that carries the load — completeness plus prioritisation is the signal.

Show solution
Client
  |
  v
[API gateway] --write--> [App servers] --> [ID generator] --> [DB: id -> long_url, sharded]
  |                                              (base-62 counter / Snowflake-style)
  |--read (GET /abc123)--> [App] --> [Cache: id -> long_url]  --hit--> 301 redirect
                                         |--miss--> [DB] --> populate cache --> redirect
Analytics: click events --> [queue] --> async aggregation  (off the hot path)
  • API: POST /shorten {long_url} → {short}; GET /{id} → 301.
  • Data model: id (PK, base-62) → long_url, created_at, ttl.
  • ID gen: a counter encoded base-62 (or Snowflake IDs) — avoids collision checks that a random hash would need.
  • Load-bearing component: the cache — 40k reads/s make it the difference between a fast redirect and a hammered DB.

Covering all pillars then pointing to the one that carries the load shows you can both be complete and prioritize.

Exercise 4 · Deep-dive the bottleneck the interviewer picksExpert

Context: The senior signal is a failure analysis: when the interviewer kills the cache node, you name the failure mode (thundering herd) and give layered mitigations, not just "add another cache".

Your task: The interviewer says: "The cache node fails. Walk me through what happens and how you'd prevent an outage." Give the failure analysis and the mitigation.

Requirements:

  • Trace the failure: cache loss → every read misses → the DB is hit all at once → cascading timeouts
  • Name it: the thundering herd
  • Mitigate with a replicated/clustered cache so one failure loses a shard, not everything
  • Guard the herd: request coalescing (single-flight) and jittered TTLs
  • Protect the DB: a concurrency limiter / circuit breaker for graceful degradation
  • Warm hot keys on deploy so a cold cache isn't empty

💡 Hint: Naming the failure mode and layering the mitigations (don't-run-one-node, coalesce, protect-the-DB, warm) is what reads as senior.

Show solution

What happens on cache loss: every read misses → all ~40k reads/s hit the DB at once (a thundering herd) → DB latency spikes → timeouts cascade to the app tier.

Mitigations, in order of leverage:

  1. Don’t run one cache node. Use a replicated/clustered cache so a single failure loses a shard, not everything.
  2. Guard the herd: request coalescing (single-flight) so 10k concurrent misses for the same key trigger one DB read, plus jittered TTLs so keys don’t all expire together.
  3. Protect the DB: a concurrency limiter / circuit breaker in front so a cache-cold event degrades gracefully (some slow redirects) instead of taking the DB down.
  4. Warm on deploy: pre-populate hot keys so a cold cache isn’t empty.

The move that separates senior from mid: naming the failure mode by name (thundering herd) and giving layered mitigations rather than just “add another cache.”

Exercise 5 · Make a tradeoff explicit and defend itProfessional

Context: The professional signal is presenting a tradeoff as a table and defending a choice for this system — and naming when you'd choose the opposite.

Your task: You must choose between strong and eventual consistency for click-analytics counts. Present it as a tradeoff table and defend a choice for this system.

Requirements:

  • Table strong (sync count on redirect) vs eventual (async via queue)
  • Strong: exact count instantly, but latency on the hot path and analytics coupling
  • Eventual: low latency and decoupled, but counts lag and you need a queue + consumer
  • Choose eventual here because the redirect is sacred and analytics can lag seconds
  • Name the exception (e.g. billing counts) where you'd pay for strong consistency

💡 Hint: Protect the SLA that matters — the redirect — and let analytics lag; naming when you'd flip the choice is what proves you're reasoning, not guessing.

Show solution
📋 Consistency choice for click counts
Strong (sync count on redirect)Eventual (async via queue)
Redirect latencyHigher — write on hot pathLow — count off the hot path
AccuracyExact, instantlyExact within seconds, may lag
Failure blast radiusAnalytics DB down → redirects failQueue backs up; redirects unaffected
Cost/complexitySimpler code, worse couplingNeeds a queue + consumer

Choose eventual. For a shortener, the redirect is sacred and analytics can lag a few seconds — decoupling protects the SLA that matters. I’d state the exception: if this were billing counts, I’d pay the latency for strong consistency. Naming when you’d choose the opposite is the professional signal.

Exercise 6 · Read the seniority ladder in the roomIndustry scenario

Context: The same prompt is scored differently for mid, senior, and staff. Knowing what a passing answer looks like at each level tells you what to reach for.

Your task: The same "design a rate limiter" prompt is scored differently for mid vs staff. Write what a passing answer looks like at each level (mid, senior, staff), so you know what to reach for.

Requirements:

  • Mid: a correct algorithm (token bucket), the data structure, the distributed case (shared counter), the complexity
  • Senior: all of that plus failure modes (fail-open vs fail-closed), sync overhead, algorithm choice with reasons
  • Staff: all of that plus the product framing (per user/IP/key? business goal?), org cost as shared infra, safe rollout/observability
  • State the core axis: mid = correct, senior = correct under failure, staff = correct for the org and business
  • If targeting senior, volunteer the failure analysis before being asked

💡 Hint: Climb the same answer: correct, then correct-under-failure, then correct-for-the-organization — each level adds a layer rather than replacing one.

Show solution
📋 Same prompt, different bar by level
LevelWhat a pass looks like
Mid (E4)Correct token-bucket, states the data structure, handles the basic distributed case (shared counter in Redis), knows the complexity.
Senior (E5)All of the above + failure modes (Redis down → fail-open vs fail-closed decision), the sync overhead of a shared counter, and picks an algorithm (sliding-window vs token-bucket) with reasons.
Staff (E6)All above + frames the product question (rate-limit per user? per IP? per API key? what’s the business goal?), the org cost of the limiter as shared infra, and how it’s rolled out/observed/tuned safely across many teams.

Notice the axis: mid = correct, senior = correct under failure, staff = correct for the org and the business. If you’re targeting E5, don’t stop at the working design — volunteer the failure analysis before you’re asked.

✓ Checkpoint — you can move on when you can…

  • Drive the 5-step method in 45 minutes.
  • Estimate capacity out loud.
  • Cover API/data/architecture and scale the bottleneck.
  • Name tradeoffs + failure modes at the target seniority.

Knowledge check check yourself

✓ Knowledge check

What is the 5-step method for driving a system-design interview, and roughly how long do you have to run it?

Show answer
Requirements (functional + non-functional) → Estimate (users/QPS/storage) → API → Data model (+ shard key) → Architecture (client→LB→service→cache/DB, then scale the bottleneck) — driven out loud in about 45 minutes.
✓ Knowledge check

What distinguishes a senior-level system-design answer from just naming the right components?

Show answer
Naming explicit tradeoffs and failure modes — e.g. "SQL gives me transactions but caps write scale, so I'll shard / add a cache / accept eventual consistency here" — plus deep-diving one bottleneck and discussing what happens when a component dies.
© 2026 studybydoing.in · AI Engineering: Zero to Production · All rights reserved. · About · Privacy Policy · Terms · Contact
Educational content, provided as-is and without warranty. Code samples are examples — review, test, and adapt them before using in production. See the Terms of Use & Disclaimer. Use at your own risk.
© studybydoing.in