Skip to main content

Framework: Patterns and Tradeoffs in System Design

Decompose any system design question into ten path patterns, then reason through seven recurring decisions — naming the axes, the context, and the cost.

System design questions look endlessly varied, but take one apart and it is almost always built from a handful of paths: an upload path, a read path, a background-processing path, a push path. Each kind of path has a fixed shape, a fixed hard part, and a fixed set of standard moves. And at every hard part you make a choice that has to be defended out loud.

This framework organizes both halves into one structure. Patterns tell you what the system is made of; tradeoffs tell you how to choose at each joint. The goal is a single capability: handed a question you’ve never seen, you can say which known patterns it’s made of, how they connect, and what to discuss when you go deep — and you can defend every choice along the way.

Every other system design page on this site plugs into it. Walkthroughs are worked examples of patterns; concept references are layer-3 mechanisms; the 9-week plan is the order to learn them in.

The problem

Two failures dominate senior system design rounds, and they look unrelated.

The first is memorizing systems instead of shapes. You prepared News Feed, Chat, and URL Shortener. The interviewer asks you to design a satellite fleet manager, or an online judge, or a feature-flag service. None of your prepared systems match, so you start from a blank page — and spend fifteen minutes rediscovering things you already know, because you filed them under “News Feed” instead of under “one write that must be read in many other places.”

The second is “it depends.” Interviewers hear it thirty times a day. The candidates who pass don’t stop there — they name what it depends on, commit to one side, and say what they’re giving up. Candidates who fail list options without committing, or pick a side without naming the cost. Under interview pressure, with working memory full, most engineers revert to the failing version.

These are the same problem at two altitudes. The first is not knowing where the hard parts are; the second is not knowing how to talk once you’re there. A senior answer needs both: decomposition gets you to the right joints fast, and tradeoff reasoning is what you say at each joint.

Important

Key takeaway: Patterns are visible; decisions must be derived. The question says “users upload videos” — it never says “there’s a skew problem here.” So you decompose with patterns first, then go deep with decisions, and you make every decision legible with the same four steps: axes, context, cost, commit.

The framework: four layers

LayerWhat it isThe question it answersHow you use it
0 · Building blocksLoad balancer, stateless services, cache, database, log / queue, object store, CDN, ID generationWhich boxes do I draw by default?Present in every design; no recognition needed
1 · Path patternsTen path shapes, plus one extension (expensive compute)Which paths is this question made of?Recognize from signals in the prompt; draw the diagram
2 · DecisionsSeven recurring decisions: five inside a path, two between paths — each argued with the four tradeoff stepsWhat do I have to choose on each path, and how do I defend it?Your deep-dive checklist; most senior signal comes from here
3 · ConceptsConcrete mechanisms: consistent hashing, sagas, watermarks, fencing tokens…How is this decision actually implemented?Called on when the interviewer pushes for detail

Two rules govern the whole thing:

  • A pattern describes a path, not a whole system. Don’t say “Instagram is a feed question.” Say “Instagram has a large-object upload path, a fan-out path, a read path, and a search path.” Composition falls out naturally.
  • Patterns are seen; decisions are derived. You can spot a pattern from the wording of the prompt. You can’t spot a decision — you have to ask the question that reveals it (“what does the follower distribution look like?”).

Layer 0: Building blocks

These appear in almost every design, and each has a default way to scale. Draw them without justifying why they exist; spend your words on the paths.

BlockDefault scalingGo deeper
Load balancer + stateless servicesScale horizontally; services hold no stateLoad Balancing & Service Discovery
CacheCache-aside; size by memory (working set), not by QPSCaching Patterns
Database (relational / KV / wide-column)Choose by access pattern, partition by key, add replicasSQL vs NoSQL · Database Indexing · Storage Engines
Partitioning and replicationPartition key + leader/follower or leaderlessPartitioning · Replication · Consistency Models
Log / queueScale by partition; consume with consumer groupsQueue vs Log · Queue Delivery Semantics
Object store + CDNBlobs are immutable; the CDN is the read pathCDN & Edge Delivery · CDN walkthrough
ID generationRange allocation or Snowflake-styleUnique ID Generation
APIs, auth, resilienceREST / gRPC, token auth, timeout + retry + circuit breakerAPI Design Patterns · Authentication & Authorization · Resilience Patterns

Note

Interview signal: When the question is a building block — design a distributed KV store, Kafka, Memcached, a distributed lock, an ID generator — you are being asked to open one block up. The content is then partitioning, replication, quorums, version vectors, repair, and consensus (Quorums & Conflict Resolution · Anti-Entropy · Consensus), all answered inside one component. These questions get more common above senior level. The Distributed Key-Value Store walkthrough is the model answer for this category; the Distributed Database, Queue, Lock, and Cache walkthroughs are the rest of it.

Layer 1: The ten path patterns

#PatternSignals in the promptStandard shapeDominant decisionsExample systems
P1Key lookupFetch by ID; reads vastly exceed writes; data rarely changesMulti-tier cache + KV store; the write path guarantees ID correctnessC, DURL shortener, product page, profile page
P2Retrieval & rankingSearch, recommend, nearby, autocomplete, compare prices; can’t fetch by keyIndex + funnel: retrieve → rank → filter; or scatter-gather across sourcesA, DSearch, recommendations, nearby drivers, typeahead, flight search, RAG retrieval
P3Write-then-deriveWritten once, must be read elsewhere, in another shapeSource of truth + events → async materialized views (fan-out, indexes, counts)A, CFeed fan-out, search indexing, CDC
P4Event aggregationCount, stats, leaderboards, trends, monitoring, alerts; events vastly outnumber queriesLog → windowed aggregation → summary store; batch reconciliationD, CAd clicks, metrics, top-K, trending, leaderboards
P5ContentionLimited slots, stock, or quota; “must not oversell”; bidding; rate limitsShed traffic tier by tier + atomic decrement / single writer + holds with a TTLE, GFlash sale, ticketing, rate limiter, auction, driver locking
P6Workflow / sagaCheckout, payment, state machines; spans services; must roll backDurable state machine / orchestrator + idempotent hops + compensationsG, FOrders, payments, trip lifecycle, agent loops
P7Background jobsBackground, scheduled, batch, crawl, transcode, retryDurable queue / scheduler + worker pool + leases + retries and a DLQG, ECrawler, job scheduler, notification sending, transcoding, online judge
P8Real-time connectionsLive, presence, push, chat, co-editing, live commentsGateways that only hold sockets + routing registry + durable store as truthB, GChat, presence, live comments, collaborative docs
P9Large objectsFiles, images, video; upload, download, syncContent split from metadata + chunks and content addressing + commit content before pointer + CDNF, CVideo platform, file sync, photo upload
P10Control planeConfig, deploy, release, firmware, feature flags, experiment config; “bring a fleet to some state”Versioned desired state + agents reporting actual state + reconcile loop + staged rollout with rollbackF, GDevice / IoT fleet management, deploy systems, config service, experimentation platform
Ext.Expensive computeModel inference, GPUs, per-token billingAdmission control + continuous batching + KV / prefix cache + routingE, ALLM serving

Boundaries people confuse

  • P1 vs P9. Both are “immutable content, skewed popularity, the cache is the architecture.” P1 reads small keys, and the hard parts are ID correctness and caching. P9 moves large files, and the hard parts are the upload pipeline, the processing pipeline, and metadata consistency.
  • P3 vs P4. P3 turns one write into many views (1 → N). P4 turns many events into a few numbers (N → 1).
  • P5 vs P6. P5 is many requests fighting over one thing. P6 is one request crossing many services. A flash-sale checkout has both: grabbing the stock is P5; payment and shipping after the decrement is P6.
  • P6 vs P7. P6 cares about cross-service correctness (compensate, stay consistent). P7 cares about the throughput and scheduling of many tasks (who does it, when, and what happens on failure).
  • P8 vs P10. P8 delivers messages to clients that are online. P10 makes devices converge on a state; a device can be offline for days, and when it returns it catches up on state, not on a replay of every message.

P1 · Key lookup

  • Signals: fetch by ID or short key; read:write above 100:1; data barely changes after creation.
  • Core tension: the read path is enormous, so the cache is the architecture — but correctness lives on the write path: no two URLs may ever share a short code.
  • Standard moves:
    • Estimate first, and arrive at “no database serves this read rate directly.” That number justifies the CDN, application cache, and KV tiers.
    • Generate IDs from a range-allocated counter plus base62, which removes collisions by construction — instead of check-then-insert with retries.
    • Size the cache by the memory of the working set, not by QPS.
    • Immutable data almost never needs invalidation; set the TTL a little below the expiry.
    • Push side effects like click analytics onto an async event stream (it becomes a P4 path) so they never slow the main path.
  • Cost: a brief inconsistency window after writes — usually fine for this kind of product.
  • Traps: treating the ID scheme as a detail; a cache outage that turns into a stampede because you never mentioned request coalescing.
  • Follow-ups: Why 302 rather than 301? What happens to an app server’s ID range when it crashes? What happens when Redis dies at peak?
  • Anchor: URL Shortener — a 100:1 read ratio; the cache is the architecture.
  • Read next: Caching Patterns · Unique ID Generation

P2 · Retrieval & ranking

  • Signals: search, recommend, nearby, autocomplete, compare; the result can’t be fetched by key — it has to be found inside a large set.
  • Core tension: the corpus is too big to score every item, so it must be a funnel — and each stage has a different job and a different metric. Blur them and things break.
  • Standard moves:
    • Justify the funnel with arithmetic: 100M items × per-item scoring cost is far beyond the latency budget.
    • Judge retrieval by recall (wide, overlapping sources); judge ranking by precision (fresh features).
    • Apply visibility (permissions) at retrieval time, not after ranking — otherwise you waste compute and risk returning an empty page.
    • Define each feature once, materialize it in two places, to prevent training-serving skew.
    • Shard search by document; control tail latency with hedged requests and partial results.
    • “Nearby” is retrieval on a spatial index — a geohash query scans 9 cells, not 1.
    • When the sources are external (airlines, hotels), retrieval becomes scatter-gather: parallel requests, timeouts, partial results, and short-TTL caching.
  • Cost: several stages to maintain separately; recommenders carry feedback-loop bias that you hedge with exploration.
  • Traps: “just use Elasticsearch”; treating retrieval as a worse ranker; filtering visibility only after ranking; scanning one geo cell.
  • Follow-ups: What is training-serving skew? A private post leaked to a non-friend — how? Why nine cells?
  • Anchor: News Feed’s follow-up “switch from chronological to relevance”: merge the candidates first, then add a scoring layer.
  • Read next: Post Search · Recommendation System · Full Ranking System · Geospatial Matching · Inverted Index · Two-Stage Ranking · ANN Indexes · Geospatial Indexing

P3 · Write-then-derive

  • Signals: one write must become visible elsewhere, or queryable in another shape — a new post lands in followers’ feeds, a product update lands in the search index, one relationship must be queried from both directions.
  • Core tension: write cost scales with fan-out, and fan-out follows a power law. Design for the average and you will fall over on the single most extreme user.
  • Standard moves:
    • Ask for the distribution of the skew, not the average.
    • Keep the write path to the authoritative record plus one event; fan out in async workers.
    • Push for ordinary users at write time, pull for extreme users at read time, and merge-and-dedupe at read time.
    • Use a log-based stream, because replay is how you repair a fan-out bug.
    • Model data around the queries: every hot query is a single-partition read, which is why one relationship is often stored as two inverse tables.
  • Cost: two paths and a threshold policy to maintain; a new read-side hot spot (the celebrity account being pulled).
  • Traps: designing for the average user; storing ranking scores in the inbox (rank at read time); forgetting to dedupe after the merge.
  • Follow-ups: What happens when a celebrity posts? Why two follow tables? A user posts, refreshes, and doesn’t see their own post — why?
  • Anchor: News Feed — one post, fanned out asynchronously into every follower’s inbox.
  • Read next: NoSQL Hot Key Mitigation · SQL vs NoSQL Schema Design · Queue vs Log

P4 · Event aggregation

  • Signals: counts, stats, leaderboards, trends, monitoring, alerts; a flood of events in, a few summary numbers out.
  • Core tension: freshness versus correctness. A fast streaming path can answer “roughly what is it now” but can be silently wrong; billing needs “what is true.”
  • Standard moves:
    • Give each goal its own owner: the streaming path owns freshness; a batch path over the immutable raw log owns correctness and may overwrite the stream’s results (Lambda). Or keep only the stream and correct by replaying the log (Kappa).
    • Inside the stream, handle event time, watermarks, and late data.
    • Exactly-once comes from dedup, atomic checkpoints, and a transactional sink together — and say that it ends where side effects leave the framework.
    • Hot keys get two-phase aggregation: salt to spread, then merge.
    • When exact isn’t required, use approximate structures (Count-Min Sketch + Space-Saving for top-K).
    • A time-series system’s capacity limit is the number of series (cardinality), not the number of samples — cap cardinality at ingest.
  • Cost: two paths to maintain and keep in agreement.
  • Traps: a single Kafka-to-database pipe; claiming exactly-once without stating its boundary; an alerting path that fails silently itself.
  • Follow-ups: What about late events? One ad takes 10% of all traffic — now what? Why is cardinality the bottleneck of a metrics system?
  • Anchor: Ad Click Aggregation — a firehose of click events, aggregated by time window into counts.
  • Read next: Metrics & Monitoring · Top K · Consecutive Activity Aggregation · Stream Processing · Approximate Counting · Time-Series Storage

P5 · Contention

  • Signals: limited slots, stock, or quota; “must not oversell”; many requests fighting for the same thing at once; bidding; rate limits.
  • Core tension: the hard part is contention, not throughput. Correctness isn’t a switch you flip — it’s the result of where you put the atomic operation, the key, and the TTL.
  • Standard moves:
    • Make most requests lose at the cheapest tier: CDN, bot checks, gateway, admission tokens / virtual queue — and only then the sharded inventory.
    • Use an atomic, guarded decrement, never read-then-write.
    • Use holds with a TTL, so a crash can’t lock the resource forever.
    • When strict ordering matters (auction bids), serialize through a single-writer actor.
    • Acquire multiple resources in a fixed order to prevent deadlock.
    • Choose the direction of failure: for zero-tolerance stock, undersell rather than run async replication with failover; for a rate limiter, decide whether Redis going down means fail-open or fail-closed.
  • Cost: one heavily protected hot spot; some requests are rejected.
  • Traps: database row locks at a million QPS; reading the counter, then writing it (two gateways both see “1 left”); holds without a TTL.
  • Follow-ups: Two customers race for the last item — who wins? A Redis shard fails over right after selling out — what happens? The rate limiter’s Redis dies — now what?
  • Anchor: Flash Deal — most requests are turned away in the first few tiers, before they ever touch inventory.
  • Read next: Rate Limiter · Auction · Rate Limiting Algorithms · Distributed Lock · Distributed Locks & Fencing · Isolation & MVCC

P6 · Workflow / saga

  • Signals: checkout, payment, refund, trip lifecycle; one business operation spans several services; a failure midway must roll back.
  • Core tension: partial failure across services. You can’t lock every service in one big transaction, but the outcome must be consistent.
  • Standard moves:
    • Across services, use a saga rather than 2PC: a chain of local transactions, each with a compensating action.
    • Persist the orchestrator’s state — it is itself a state machine.
    • Retry first, compensate last; put non-compensable steps (shipping, charging an external account) at the end.
    • Carry an idempotency key, derived from the business operation, on every hop.
    • Use an outbox to solve the dual write between “update the database” and “publish the message.”
    • Reconcile periodically with external systems (payment gateways), because they can’t promise exactly-once.
    • Agent loops share this shape: checkpoint every state transition; put an approval gate before irreversible actions.
  • Cost: eventual consistency; complex compensation logic; idempotency keys to store.
  • Traps: “just use a distributed transaction”; orchestrator state held in memory; compensations that aren’t idempotent themselves.
  • Follow-ups: The compensation fails — then what? The payment gateway times out but actually charged the card — then what? The orchestrator crashes midway — then what?
  • Anchor: Order Processing — payment, inventory, shipping, notification; any step can fail and must be compensated.
  • Read next: Distributed Transaction Patterns · Agent Orchestration · Idempotency & Outbox

P7 · Background jobs

  • Signals: background tasks, scheduled tasks, batch processing, crawling, transcoding, sending notifications, judging submissions; “accept now, finish later.”
  • Core tension: many tasks must run reliably on a limited worker pool — none lost, none harmfully run twice, and not dragged down by one large tenant or one batch of poison messages.
  • Standard moves:
    • Persist the task to a queue or scheduler before returning “accepted.”
    • Workers claim tasks under a lease (visibility timeout); an expired lease returns the task to the queue; results carry a fencing token so a stale worker can’t overwrite them.
    • Delivery is at-least-once, so task handling must be idempotent.
    • Retry with exponential backoff plus jitter; past the limit, send to a DLQ.
    • Separate queues by priority and tenant so low-priority work or a large tenant can’t starve everyone else (in notifications: critical alerts never wait behind marketing).
    • Use a timing wheel or bucketed delay queues for scheduled and delayed tasks — not database polling.
    • Multi-step jobs (transcode: split → transcode in parallel → write manifest) are a DAG, where every step is an independently retryable job.
  • Cost: task-state storage; duplicate execution is always possible and can only be absorbed by idempotency.
  • Traps: scheduling by polling SELECT ... WHERE run_at < now(); leases without fencing, so two workers run the same task; retries without backoff, causing an avalanche; no DLQ, so one poison message blocks the whole queue.
  • Follow-ups: A worker crashes halfway through — what happens? A million tasks come due at the same instant — what happens? One tenant floods the queue — what happens?
  • Anchor: Distributed Job Scheduler — the worker dies mid-task, its lease expires, and the task goes back to the queue.
  • Read next: Notification System · Queue Delivery Semantics · Timing Wheels & Delay Queues · Distributed Locks & Fencing

Tip

Why it deserves its own practice: Background jobs rarely get top billing in a prompt, so prep material tends to scatter them across notifications, transcoding, and schedulers. But they’re one of the most frequent patterns in high-frequency questions — crawlers, schedulers, online judges, firmware rollouts. Practice them as a pattern, not as a side detail of other systems.

P8 · Real-time connections

  • Signals: real-time, presence, push, chat, co-editing, live comments.
  • Core tension: connections are stateful and bound to one server, but delivery routing has to be global. The real load is often “100M long-lived connections,” not message volume.
  • Standard moves:
    • Compare WebSocket, SSE, and long polling before choosing.
    • Connection servers only hold sockets; a registry or pub/sub answers “which machine holds this user’s socket?”
    • Delivery is at-least-once plus client-side dedup; an idempotency key turns it into exactly-once from the user’s point of view.
    • Guarantee order only within a conversation: one conversation’s messages land on the same partition owner.
    • The durable store is the truth; a push notification is only a wake-up signal. Offline users catch up from the store when they return.
    • Co-editing: one owner worker per document as the single writer; the offline-editing requirement decides OT versus CRDT.
  • Cost: the connection fleet, the durable delivery pipeline, and offline push are three tightly coupled systems.
  • Traps: defaulting to WebSocket; treating push as the delivery mechanism; deploying connection servers by dropping every connection at once, causing a reconnect storm.
  • Follow-ups: A user sends from two devices at once — how is order kept? A connection server restarts — what happens? A 10,000-member group chat — how does a message fan out?
  • Anchor: Chat System — “which machine holds this user’s socket?”
  • Read next: Collaborative Editor · Real-Time Connection Patterns · Load Balancing & Service Discovery

P9 · Large objects

  • Signals: files, images, video; upload, download, sync, backup, transcode.
  • Core tension: content and metadata have opposite personalities. Content is immutable and huge; metadata is mutable and needs transactional consistency.
  • Standard moves:
    • Split content and metadata into two systems and design them separately.
    • Content-address content by hash and store it in fixed-size chunks — which buys resumable upload, dedup, delta sync, and cheap versions all at once.
    • On upload, commit the content first and the pointer last, so a crash leaves garbage, not corruption.
    • Processing (transcoding, thumbnails) is derived data, handed to P7 jobs; video transcodes in parallel by “segment × rendition,” then writes a manifest.
    • Delivery runs through a CDN, and what you design is the miss stream: request coalescing, a shield tier, admit-on-second-hit.
    • Express change as a new versioned URL; purge is for emergencies.
    • File sync: what you design is sync bookkeeping (sync cursors, keep both copies on conflict), not just transfer.
  • Cost: garbage collection gets hard — reference counts are spread across a sharded metadata tier, and GC has to coordinate across shards.
  • Traps: “a blob store plus a CDN plus FFmpeg”; uploading a whole file in one POST; designing only the cache box; designing file transfer instead of file sync.
  • Follow-ups: Walk the pipeline from upload to playback. How does CDN invalidation work? A million users request a brand-new object at once — what happens to the origin?
  • Anchor: File Storage & Sync — content first, pointer last: a crash leaves garbage, not corruption.
  • Read next: Video Streaming · CDN · CDN & Edge Delivery

P10 · Control plane

  • Signals: config, deploys, releases, firmware updates (OTA), feature flags, experiment config; “bring a fleet of devices or machines to some state”; devices may be offline for long stretches.
  • Core tension: the control plane has to reliably change the state of thousands of data-plane nodes — but nodes go offline, changes fail, bad changes must be reversible, and the control plane itself must never become the data plane’s point of failure.
  • Standard shape:
    • Desired state — versioned, stored in a small strongly consistent store; the single source of truth.
    • Actual state — reported by agents; a derived view.
    • Reconcile loop — diff the two and push nodes toward desired state; the loop is idempotent and safe to rerun at any time.
    • Rollout controller — release in stages with a health gate between stages; a tripped gate halts and rolls back.
  • Standard moves:
    • Declarative, not imperative: ship “what the state should be,” not “run this command.” Lose one imperative command and state drifts.
    • Bump a version on every change; resolve concurrent edits with a CAS on the version.
    • Agents pull (long polling) by default, with push notifications as a hint; a returning device compares versions and catches up on the diff, not on a replay of history.
    • Stage rollouts (1% → 10% → 50% → 100%) with health gates fed by data-plane metrics; nodes keep the last good version locally and roll back on failure.
    • Static stability: if the control plane is down entirely, the data plane keeps running on the last valid config.
    • When connectivity is intermittent (a satellite pass window), precompute the batch to send outside the window; inside the window, only transmit.
  • Cost: there is always a convergence delay between the two states; staged rollouts slow releases down.
  • Traps: sending commands one by one; releasing to the whole fleet at once; the data plane reading config from the control plane on every request, so a control-plane outage takes everything down; no rollback path.
  • Follow-ups: A device comes back after three days offline — what does it get? Errors climb at the 10% stage — what happens? Two operators edit the same device’s config at once — what wins? The control plane goes down — what does the data plane do?
  • Anchor: the satellite fleet example below — three days offline, and it catches up on the diff, not a replay.
  • Read next: Consensus · Anti-Entropy · Resilience Patterns

Extension · Expensive compute

  • Signals: model inference, GPUs, per-token billing, nondeterministic output.
  • Core tension: the scarce resource is GPU memory, not request routing; cost scales with tokens, not requests.
  • Standard moves: in LLM serving the budget is the KV cache, not the weights — so use continuous batching and a paged KV cache for utilization, and prefix caching with prefix-aware routing to cut prefill cost. Protect the GPUs with admission control and queuing (a variant of P5).
  • The rest of an AI system is composition of patterns you already know:
    • RAG = P2 (hybrid retrieval + rerank), with retrieval and generation evaluated separately.
    • Agents = P6 (a checkpointed state machine) plus budgets, approval gates, and sandboxing.
    • Vector database = the index inside P2, trading recall against latency against memory.
  • Traps: static batching; tuning prompts when retrieval never found the answer; agent loops without a budget.
  • Read next: LLM Serving · RAG System · Vector Database · Agent Orchestration · ANN Indexes

Layer 2: The seven decisions

Patterns give you the boxes. Decisions are where the interview is scored. Five decisions live inside a path; two live between paths and hold the composition together.

Five decisions inside a path

#DecisionThe question to askTypical optionsAnchor
AWhere the work happensCompute at write time, read time, or async? Is it on the critical path?Push / pull; precompute / compute on demand; sync / asyncURL shortener: the redirect never waits for analytics — click events go onto a queue
BPartitioning & ownershipPartition by what key? Who owns which piece of state?By user / document / region / device; single-owner workers; stateful vs statelessKV store: consistent hashing — adding a node moves only ~1/N of the data
CSkewWhere is the power law? What do you do with the few extreme keys?A separate path for the few; salting; tiered caches; two-phase aggregationNews feed: a handful of celebrities hold a disproportionate share of follows → pull them at read time
DCorrectness budgetHow stale, how approximate, how provisional can the result be?Strong / eventual / read-your-writes; approximate structures; stream first, correct with batchKV store: under a partition, must writes succeed (AP) or be refused (CP)?
EOrdering & contentionWhich operations must be serialized? Who serializes them?Atomic ops; single writer; conditional update / CAS; lease + fencing tokenRate limiter across machines: two gateways both see “1 left” → check-and-decrement must be atomic

Two decisions between paths (the glue)

#DecisionThe question to askTypical optionsAnchor
FSource of truth & derivationWhich data is the truth? What can be rebuilt from it?Event log; outbox; materialized views; replay; version numbersAd clicks: the immutable raw log is the truth; every aggregate can be recomputed from it by batch
GFailure, retry & overloadWhat happens on partial failure? What gets shed first under overload? Which way do you fail?Idempotency keys; at-least-once; saga compensation; load shedding; priority isolation; fail-open / fail-closedOrder processing: the downstream processed it but the ack was lost → an idempotency key flows from the client through every hop

Anchors come from the URL Shortener, Distributed Key-Value Store, News Feed, Rate Limiter, Ad Click Aggregation, and Order Processing walkthroughs. Remember the one point, and the decision comes back with it.

Important

Key takeaway: Patterns almost always connect through two things: events (a log or an outbox) and derived views. That’s why F and G are the keys to composition. Upstream writes the truth and emits an event; downstream consumes the event and builds a view. At every seam, the event must not be lost (outbox) and duplicate delivery must be harmless (idempotency).

Making a decision out loud: the four steps

Naming the decision isn’t enough; you have to argue it. Every decision above gets the same four steps. Do all four and you’ve done the reasoning; skip one and you haven’t.

  1. Name the competing axes — what you’re trading between.
  2. Explain the context that breaks the tie — what about this system favors one side.
  3. State the cost you’re accepting — what you lose, and why it’s tolerable here.
  4. Commit — pick a side and say it out loud.

Step 1: Name the competing axes

Not “pros and cons” — that’s a list, not a tradeoff. A tradeoff has two (occasionally three) properties where improving one degrades the other. The recurring pairs, and the decisions where each one usually shows up:

Axis pairWhat you’re choosing betweenUsually under
Consistency ↔ AvailabilityCorrect answers vs answers at all (under partition)D
Latency ↔ ConsistencyFast reads vs up-to-date readsD
Accuracy ↔ LatencyPrecise answers vs fast, approximate onesD
Write cost ↔ Read latencyCheap writes (normalize, pull) vs fast reads (denormalize, push)A
Latency ↔ ThroughputFast individual requests vs high aggregate capacityA
Coupling ↔ LatencyIndependent services (network hop) vs in-process callsB
Durability ↔ Write speedfsync every write vs batch and risk lossF
Correctness ↔ Availability under failureFail closed vs fail openG
Cost ↔ LatencyCheap infrastructure vs fast responsesC
Operational simplicity ↔ OptimalityFewer moving parts vs the best possible performanceany

The move: at a decision point, say “the tradeoff here is between X and Y” before you pick. That one sentence is the difference between “it depends” and structured reasoning.

Step 2: Explain the context that breaks the tie

Something about this system makes one side matter more. It almost always comes from one of five constraints — and most of them are exactly what the pattern’s signals already told you:

  • Access pattern. Read-heavy (P1), write-heavy (P4), or bursty (P5). Decides whether you optimize the read path or the write path.
  • Scale dimension. What is large — users, data volume, request rate, connections (P8), fan-out (P3)? The binding constraint shapes the choice.
  • Failure tolerance. What happens if this component is wrong or slow? User- facing (intolerable) or internal (degradable)?
  • Consistency requirement. Correct now (money, stock), eventually correct (a feed), or approximately correct (analytics)?
  • Mutation rate. Low mutation → cache aggressively. High mutation → the cache becomes a consistency problem.

The move: “In this system, [context] means we should favor [side].” Context is what turns a preference into a decision.

Step 3: State the cost you’re accepting

Naming the cost — explicitly, out loud — is what separates SDE III answers from SDE II answers. SDE II picks a side and explains why it’s good. SDE III picks a side, explains why it’s good for this context, and names what breaks because of it. Every pattern card above lists the cost for exactly this reason.

The move: “The cost is [what we lose]. We accept it because [why it’s tolerable here].”

Step 4: Commit

The first three steps are analysis; this one is the deliverable. Candidates who stop at step 3 sound like they’re still deliberating. Say “so I’d go with X.” If an assumption is uncertain, commit conditionally — “assuming read-heavy, X; if it’s write-heavy, Z.” A conditional recommendation is still a recommendation. Refusing to pick is the only failing move.

Three decisions, argued

Decision A in a URL shortener (P1): where does the cache live?

  • Axes: latency ↔ consistency. Edge caching skips the origin round-trip but is harder to invalidate; an application cache is a little slower but easy to invalidate.
  • Context: short URLs are effectively immutable — created once, redirected forever. The usual argument against aggressive caching barely applies.
  • Cost: a deleted URL keeps redirecting from cached copies until the TTL expires. Acceptable: deletion is an admin action, and a five-minute stale window on it is fine.
  • Commit: cache at both tiers, with long TTLs.

Decisions A and C in a news feed (P3): push or pull?

  • Axes: write cost ↔ read latency. Push makes every post N writes; pull makes every feed load N reads.
  • Context: feeds are read about 100× more than posts are written, so pay the cost at write time — except that follower counts follow a power law (decision C).
  • Cost: a 10M-follower post would be 10M writes. Acceptable for ordinary users because fan-out is async and the poster never waits; unacceptable for the tail.
  • Commit: push for ordinary users, pull for the few above a follower threshold, merged and deduped at read time.

Decisions D and G in a rate limiter (P5): Redis or Postgres for the counters?

  • Axes: latency ↔ durability. The limiter is on every request; but lost state means clients get a free burst.
  • Context: at 100K requests/second the store must answer in under a millisecond, and rate-limit state is ephemeral — losing it means brief over-admission, not corruption.
  • Cost: a Redis restart resets limits and lets clients burst for 5–10 seconds. Far cheaper than adding 10ms to every request forever. Say which way it fails (G): open, for a general API; closed, for an expensive or abuse-prone endpoint.
  • Commit: Redis, with atomic check-and-decrement.

Layer 3: Concepts

Concepts are the mechanisms you reach for when an interviewer pushes past the decision: “how exactly would the fencing token work?” Don’t lead with them — lead with the decision and its cost, then go one level down when asked. A concept named without the decision it serves is name-dropping.

  • Common System Design Decisions is the bridge between layer 2 and layer 3: the default answer for each recurring choice, and the trigger that should make you switch.
  • Each concept reference on the site is one mechanism. The pattern cards above link the ones each pattern leans on.

How to apply it: the interview, phase by phase

The interview’s structure doesn’t change: clarify → requirements and estimation → high level → deep dive → wrap-up. The four layers aren’t another process; they tell you what to look for and what to do in each phase.

PhaseWhat you do
1 · ClarifyScan the prompt for pattern signals; ask the question that decides the architecture (“what shape is the data?”, “what’s the source of truth?”, “what does the distribution look like?“)
2 · Requirements & estimationEstimate first (Capacity Estimation); use the numbers to say where the bottleneck is — this is the context you’ll cite in step 2 of every tradeoff
3 · High levelYour first sentence names the paths: “I see N paths” — writes, reads, async work, connections — each matched to a pattern, with the hardest as the main line. Then draw them on layer-0 blocks, and use F and G to wire the seams (what’s the truth, how events flow, how failures retry)
4 · Deep diveWalk the main pattern’s dominant decisions one by one, each argued with the four steps; give each secondary pattern a sentence or two on the constraint it adds. Follow-ups land here
5 · Wrap-upFailure modes, what you skipped and why, operations (monitoring, alerting, rollout)

Note

Interview signal: “List the paths, match the patterns” is not a separate step you announce. Nobody says “I will now match patterns.” You say the paths in the first sentence of the high-level design, and you start drawing.

Worked example 1: A satellite fleet manager (in detail)

Prompt (hypothetical): design a system that manages a large fleet of satellites (or satellite user terminals). Devices report telemetry; operators send commands and firmware; a satellite can only talk to a ground station during a pass window; the system monitors device health and alerts.

Nothing on this site is “a satellite system.” That’s the point.

High level, opening: list the paths, match the patterns

PathPatternWhy
Operator sets desired state (mode, parameters, firmware version) → wait for a window → device convergesP10 Control plane (main line)Desired state is the truth; devices can be offline for a long time
Firmware distribution and staged upgradesP9 + P10 + P7The firmware image is a large object; the rollout is a control plane; each device’s upgrade is a job
Telemetry reports → time series + each device’s latest stateP4 + P3A firehose of writes, aggregated, and derived into a “current device state” view
Health detection and alertingP4Rules / thresholds over the aggregates
Allocating ground-station antenna time windowsP5 + P7Antennas are scarce; windows are time-scheduled tasks

High level: draw on the blocks, wire the seams

  • Desired state lives in a small, strongly consistent store, with a version bump on every change (F).
  • Before each window, a planner computes the command batch for that window from the diff between desired and reported state (A: the work happens outside the window).
  • During the window, the ground station transmits the batch; the device executes and reports its new actual state and the sequence number of the last command it ran.
  • Telemetry flows into a log, is aggregated by the stream and written to a time-series store, and also updates each device’s reported-state view (F: reported state is derived).

Deep dive: the main line (P10’s dominant F and G, plus B and E)

  • B · Partitioning & ownership. Partition by device; each device’s command queue has exactly one owner, so two schedulers can never send one satellite conflicting commands.
  • E · Ordering. Commands per device carry monotonically increasing sequence numbers; the device only executes numbers above its last executed one. Two operators editing one device’s desired state at once resolve with a CAS on the version — the later edit must build on the latest version.
  • G · Failure and retry. Commands are naturally resent (packets drop inside a window), so they must be idempotent. A missed window rolls to the next. A device back after three days offline gets “the diff between current desired state and what it has” — not three days of replayed commands.
  • G · Release safety. Firmware rolls out 1% → 10% → 50% → 100%, with a health gate between stages (error rates and reboot counts from telemetry); a tripped gate halts and rolls back. The device keeps the previous good image (A/B partitions) and falls back on its own if an upgrade fails.
  • F · Static stability. If the whole control plane is down, devices keep operating on their last valid config. A management outage never makes the fleet uncontrollable.

One decision argued in full, to show the four steps landing on a new system: should the ground station push commands, or the device pull? Axes: freshness ↔ robustness to missed contact. Context: contact only happens in short, predictable windows, and devices may miss several. Cost: with declarative pull-on-contact, a change waits for the next window — minutes to hours of convergence delay. Acceptable, because the alternative (imperative push) corrupts state the first time a command is lost. Commit: declarative desired state, reconciled on every contact.

Deep dive, closing: a sentence or two per secondary pattern

  • Telemetry (P4): cardinality is the capacity ceiling — estimate devices × metrics; and the alerting path itself needs monitoring.
  • Antenna scheduling (P5 + P7): windows are predictable (orbits are known), so schedule them offline in advance; on conflict, prioritize (urgent commands > routine telemetry download).

Worked example 2: Ride-hailing

The same procedure on a familiar product, compressed to the opening and the decisions that matter:

PathPattern
Drivers report location every few seconds → written into a geo indexP3
A rider requests a ride → match nearby driversP2 (main line)
Lock the chosen driverP5 (main line)
Trip → paymentP6
Pricing, surge heat mapsP4

The deep dive goes to B (partition by geography), C (dense downtown cells are the hot spots), and E (one driver must never be held by two requests). The trap is spending the round on the map and never answering E. See the Geospatial Matching walkthrough for the P2 half in depth.

More decompositions

QuestionPaths → patternsMain lineKey decisions
Photo sharing (Instagram-style)Upload photo → P9; post into feeds → P3; read feed → P1; search → P2P3A (hybrid push / pull), C (celebrities pulled)
TicketingEvent page → P1; search events → P2; grab a seat → P5 (TTL hold + virtual queue); checkout to payment → P6P5E (atomic seat hold), G (tiered load shedding)
Web crawlerURL frontier + fetch workers → P7; page storage → P9; dedup → FP7B (partition by host, for politeness), F (URL and content dedup), G (retries and dead links)
Distributed job schedulerSubmit, fire when due, assign → P7P7E (lease + fencing so two workers never run one job), G (at-least-once + idempotency)
Trending topicsPost events → sliding-window top-K → P4P4C (hot topics), D (approximate counts are fine)
Online judgeProblem page → P1; submission → judging queue + sandboxed workers → P7; result back → P8 or polling; contest leaderboard → P4P7G (judge timeouts and retries), C (the submission spike at contest start); sandbox isolation is a layer-3 concept
Collaborative docsMulti-user editing → P8; snapshots and the operation log → FP8B (one owner worker per document), E (single writer orders operations), D (offline editing decides OT vs CRDT)
Experimentation platformExperiment config pushed to every service → P10; assignment → P1 (deterministic hash, computed locally); metric stats → P4P10 + P4F (versioned config), D (freshness of results), G (config service down → use the last config)
Flight searchScatter-gather across airlines → P2; fare cache → P1P2D (fares have short TTLs; reconfirm the price before booking), G (external timeouts → partial results)
Kafka / MemcachedOpen a layer-0 blockThe block itselfB, D, E, G — all answered inside one component

Where it breaks

  • When the question is the block. Design a consensus protocol, a storage engine, a distributed lock: there’s one component, no paths to compose, and the whole round is layer 3. Use the decisions as your checklist, but don’t force a path table.
  • When a keyword misleads. “Real-time” in a dashboard prompt usually means seconds-fresh aggregates (P4), not sockets (P8). “Search” over a few thousand items may be a database index, not a retrieval funnel. Patterns are recognized from signals, then confirmed with a clarifying question — never matched on a single word.
  • When you decompose too wide. Listing six paths and going shallow on all of them reads as a survey. Pick one main line, go deep on its dominant decisions, and give the rest a sentence each. If the interviewer wants a secondary path, they’ll pull you there.
  • When the round is really about product or ML judgment. In ranking- quality or experimentation-design rounds, the hard part is metrics, labels, and evaluation, not paths. The framework gets you the serving architecture; it won’t pick your objective function.
  • When it replaces mechanisms instead of organizing them. Saying “this is P5, decision E” without being able to walk an atomic guarded decrement is worse than not using the labels at all. The patterns tell you where to dig; layer 3 is the digging.
  • The extension isn’t settled. AI system design is moving fast. Expensive compute is listed as an extension, not a pattern, on purpose: its standard moves are still shifting.