Single server
App + database. Simple, fast to change, one failure domain.
Start hereBackend & distributed systems field guide
A memory-first map of how requests move, systems scale, data stays correct, and failures stay contained.
# Requirements choose the architecture
load = estimate(qps, storage, bandwidth)
path = client → edge → service → data
bottleneck = measure(latency by hop + saturation)
if cacheable_repetition_limits_origin:
test(cache)
if eligible_reads_saturate_data_node:
test(read replicas)
if deferrable_bursts_create_backlog:
test(durable queue + bounded workers)
state_tradeoffs()
design_for_failure()
measure_and_iterate()
01 · Request journey
Use this as a branching trace, not a mandatory serial stack. A cache hit returns early; deferred work leaves the synchronous response path only after a durable handoff.
02 · Scaling ladder
Each rung is a candidate intervention—not a required migration sequence. Measure the limiting resource, change the smallest useful boundary, and verify the result before climbing again.
App + database. Simple, fast to change, one failure domain.
Start hereMore CPU, memory, and disk. Easy but has a hard ceiling.
Machine is saturatedMove the database out. Scale compute and storage independently.
Resource contentionStateless replicas behind a load balancer.
Compute QPS risesReuse staleness-tolerant results or serve cacheable content nearer users.
Measured repetition or distanceCopy eligible reads for capacity; partition ownership when storage, writes, or working set exceed one node.
Data-node capacity is the limitDurable queues smooth bounded bursts; workers isolate deferrable slow jobs. Shed or throttle sustained overload.
Deferrable work + drain headroom03 · Architecture decision graph
Select the observed pressure to reveal what to diagnose, when a candidate pattern fits, and what it costs.
Break down tail latency by hop and inspect the query plan. If repeated cacheable reads dominate, test cache-aside and measure end-to-end benefit.
04 · Data decision matrix
The query shape, consistency need, and scale pattern matter more than labels.
Orders, payments, inventory, identity.
Joins · ACID · constraintsProfiles, catalogs, content records.
Nested data · schema evolutionSessions, counters, preferences.
Predictable lookup · easy partitioningSocial edges, fraud rings, knowledge graphs.
Multi-hop queries · connected dataTelemetry, feeds, and time-bucketed records queried by partition key.
Partition-local clustering order · denormalized query modelFull-text search, autocomplete, filtering.
Inverted index · ranking05 · Distributed trade-offs
When communication is lost or indefinitely delayed, an operation cannot guarantee both atomic consistency and an eventual valid response to every request received by a non-failing node. Make that failure behavior explicit instead of labeling the whole product “CP” or “AP.”
Reject or delay operations rather than expose conflicting truth.
Serve possibly stale data and reconcile later.
When communication is lost or indefinitely delayed, an operation cannot guarantee both atomic consistency and an eventual valid response at every non-failing node. Reject or wait to preserve atomic semantics, or respond from reachable state and reconcile under a weaker model; practical systems may sacrifice some of both.
Formal basis: Gilbert and Lynch’s CAP review ↗. Consistency models and session guarantees are a toolbox—not one total ordering of “strength.”
06 · Fast paths and slow paths
Remember: invalidation, stampede protection, eviction, and stale-data tolerance.
Remember: a job-only request may acknowledge after the broker confirms durable acceptance. If a database mutation must emit an event, commit business state and an outbox record in one local transaction, then relay it. At-least-once delivery means consumers must tolerate duplicates—typically with idempotent effects, deduplication state, or an atomic inbox/write transaction.
07 · Reliability stack
Layer defenses so one slow or broken service does not become a system-wide outage.
08 · Interview loop
Alex Xu’s framework is effective because it keeps the conversation requirement-led and trade-off-aware.
Users, use cases, read/write ratio, latency, consistency, geography.
Output: functional + non-functional requirementsQPS, peak factor, object size, storage growth, bandwidth, cache size.
Output: order-of-magnitude numbersAPIs, data model, components, request flow, then the critical deep dive.
Output: high-level architectureFailure modes, scaling plan, consistency, observability, security, cost.
Output: explicit trade-offsDo not treat every update as a newly retained record. Then add indexes, versions, replication, metadata, allocator overhead, compression, backups, protocol overhead, and request ingress as separate assumptions.
09 · System design thinking flow
Do not begin with components. Each step produces evidence for the next decision.
Actors, actions, data, exclusions, and priority journeys.
Latency, availability, consistency, durability, freshness, security, and cost.
Users, QPS, peak factor, read/write ratio, object size, retention, and geography.
APIs, events, identifiers, pagination, idempotency, and error behavior.
Entities, access patterns, indexes, ownership, lifecycle, and consistency boundary.
Trace one write and one read before adding scale mechanisms.
Check compute, memory, network, storage, contention, hot keys, and fan-out.
Cache, replicate, shard, queue, index, stream, batch, or move to the edge.
Timeouts, retries, idempotency, failover, degradation, recovery, and observability.
Does the final design still satisfy correctness, scale, operations, and cost?
Average and peak QPS, concurrency, seasonality, and growth.
Record size, retention, growth, relationships, and access patterns.
A ratio chooses nothing alone: check repetition, staleness tolerance, query cost, hot keys, contention, ordering, and durability.
Interactive requests, background jobs, tail latency, and geographic distance.
Consistency boundary, ordering, uniqueness, transactions, and conflict policy.
SLO, redundancy, graceful degradation, RTO, and RPO.
Regions, residency, edge delivery, replication lag, and network partitions.
Authentication, authorization, encryption, abuse, privacy, and auditability.
Observability, deployment, migration, on-call load, and failure isolation.
Compute, storage, bandwidth, managed services, and engineering complexity.
Bottleneck catalog
A bottleneck is the resource or coordination point that limits throughput, raises latency, or increases failures as load grows.
Pattern selector
These are starting hypotheses. Confirm them against consistency, failure, operational, and cost requirements.
Common pattern handbook
For every pattern, state the problem it solves, where it sits in the flow, and the new failure mode it introduces.
Use when: one application instance cannot handle peak traffic or must not be a single point of failure.
How: keep services stateless, register healthy instances, choose a routing policy, and drain instances during deployment.
Watch: uneven long-lived connections, sticky sessions, slow health checks, and overloaded downstream services.
Use when: reads repeat, values tolerate bounded staleness, and the database is the source of truth.
How: read cache → on miss read database → populate with TTL. On write, update the database and invalidate or refresh the key.
Watch: stale values, cache stampedes, hot keys, eviction, and low hit rates that add an extra network hop.
Use when: static assets, media, downloads, or cacheable responses serve geographically distributed users.
How: define cache keys and headers, choose TTLs, protect the origin, and provide an invalidation strategy.
Watch: personalized content leakage, slow purge, origin stampede, and data-residency constraints.
Use when: measured read load exhausts a data node after query and index fixes, eligible reads can accept the chosen replica semantics, and the primary retains write and replication headroom.
How: route writes to the primary and eligible reads to replicas; send read-after-write traffic to the primary or track a consistency token. Availability improves only when routing, health detection, quorum or promotion rules, and tested failover can use the copies correctly.
Watch: replica lag, stale reads, failover correctness, synchronous-replication write availability, and multiplying expensive queries across replicas.
Use when: storage, write throughput, or working set exceeds a single database node.
How: choose a high-cardinality stable partition key, route requests consistently, and design rebalancing before growth demands it.
Watch: hot partitions, cross-shard joins/transactions, resharding, global indexes, and unique ID generation.
Use when: work may safely complete later and bounded bursts, retries, or a slower dependency need durable buffering. Long-run worker capacity must exceed admitted arrival rate, or admission control must cap it; a queue does not fix sustained overload.
How: assign a stable operation ID and validate synchronously. For a job-only API, wait for durable broker acceptance before acknowledging; when a database mutation must emit work, commit business state plus an outbox record atomically and relay it. Process with horizontally scaled, duplicate-tolerant consumers; bound transient retries and isolate poison jobs in a DLQ.
Watch: database/broker dual-write gaps, ambiguous publish outcomes, duplicate delivery, queue lag, unbounded retries, ordering requirements, and backpressure.
Use when: multiple systems react to the same event, consumers evolve independently, or replay is valuable.
How: publish immutable domain events with versioned schemas; partition by the ordering key; consumers keep checkpoints and idempotent state.
Watch: unclear ownership, schema breaks, reordering across partitions, replay load, and eventual consistency.
Use when: a frequent selective query otherwise scans too many rows.
How: design for one high-value query and the chosen database/index type. For a typical B-tree, consider leading equality predicates, the first range predicate, required sort order, and whether included columns enable a covering read; verify with the actual query plan and keep the index narrow.
Watch: engine-specific rules, slower writes, extra storage, unused indexes, low-selectivity fields, and indexes whose leading columns or ordering do not match the query.
Use when: dashboards, feeds, counts, or rankings repeatedly derive the same expensive result.
How: update the derived view from transactions or events, store a rebuild path, and expose freshness explicitly.
Watch: stale or divergent views, write amplification, difficult backfills, and double-counted events.
Use when: clients can overload an API, abuse is possible, or downstream quota must be protected.
How: choose the identity and scope, apply token bucket or sliding-window logic near the edge, and return clear retry information.
Watch: distributed counters, clock/window boundaries, shared-NAT users, fail-open versus fail-closed behavior.
Use when: a remote dependency can become slow or unavailable and requests otherwise wait or retry indefinitely.
How: enforce deadlines, isolate pools per dependency, open the circuit after a threshold, probe recovery, and provide fallback behavior.
Watch: thresholds that flap, hidden failures, stale fallback data, and breakers without upstream load shedding.
Use when: clients, queues, or networks may retry create, payment, or mutation requests.
How: attach a stable operation key, atomically store its result with the mutation, and return the original result on duplicate requests.
Watch: key scope, retention period, payload mismatch, races, and operations whose side effects happen outside the transaction.
Use when: a business operation spans independently owned services and partial completion must be repaired.
How: persist each step, trigger the next step, define compensating actions, make every handler idempotent, and expose workflow state.
Watch: compensation that cannot truly undo effects, long-running state, concurrent workflows, and poor observability.
Use when: partitioned caches or stores frequently add/remove nodes and simple modulo hashing would remap most keys.
How: map keys and nodes into an ordered hash space so membership changes remap only part of the keyspace; use virtual nodes or another balancing method. Replication to successor nodes is an optional layer, not a property of consistent hashing itself.
Watch: skew, coordinated membership, replication during churn, and the fact that hot keys remain hot.
Use when: one node must schedule work, own a partition, allocate IDs, or perform a singleton task.
How: acquire a consensus-backed lease and attach a monotonically increasing fencing token to every protected operation. The protected resource must reject stale tokens; do not rely only on a paused former owner noticing lease loss.
Watch: split brain, clock assumptions, long pauses, stale leaders, and making the leader a throughput bottleneck.
Yes: stop adding components. No: name the measured or projected bottleneck.
State what becomes stale, duplicated, reordered, unavailable, or harder to recover.
Every new datastore, queue, region, and cache adds failure modes and ownership.
Choose SLIs, load tests, alerts, capacity thresholds, and rollback signals.
10 · Quantitative design workbench
Interview arithmetic is not a capacity promise. It is a fast way to expose the dominant path, choose a first design, and name what must be measured before production.
Assume two million purchase attempts arrive over ten minutes, peak traffic is five times the average, the synchronous path targets 250 ms, responses average 2 kB, and one percent of attempts become orders.
| Invariant | Scope | Candidate mechanism | Failure test |
|---|---|---|---|
| One local payment intent/result per scoped idempotency key | Merchant + operation + idempotency key | Atomically persist local intent, result, and outbox; propagate the same authenticated key to a provider that supports idempotency. If the remote outcome is unknown, query and reconcile before retry. | The provider charge succeeds but the response is lost; prove lookup/reconciliation prevents a second charge and rejects a conflicting payload for the same scoped key. |
| Sellable inventory never drops below zero | SKU or reservation | Transactional conditional decrement, or a durable expiring reservation with an explicit release path. | Many buyers race for the last unit; a checkout crashes after reservation but before payment. |
| Messages stay ordered inside one conversation | Conversation | Per-conversation sequence numbers or one ordered partition; reject, buffer, or reconcile gaps. | Two devices send concurrently while one reconnects and replays an earlier request. |
| A short alias names at most one URL | Alias key | Conditional insert or unique constraint at the authoritative store. | Two creators claim the same custom alias at the same time. |
| A feed meets its freshness objective | Feed read | Event watermark, consumer-age SLI, and a declared stale-read policy. | Pause a consumer, build backlog, recover, and prove drain time without overloading the source. |
| Failure | User-visible behavior | Guardrail + data risk | Evidence |
|---|---|---|---|
| Cache unavailable | Serve a bounded stale result, shed optional reads, or bypass only while origin headroom remains. | Prevent a cache miss storm from saturating the source of truth; no silent indefinite staleness. | Cache-disabled peak test; hit rate, origin QPS, saturation, and stale-age SLI. |
| Primary store unavailable | Reject or delay consistency-sensitive writes, or enter a tested promotion path. | Fence stale leaders; state RPO and which reads may become stale during promotion. | Leader-loss exercise; commit latency, replica lag, stale-token rejection, recovery time. |
| Queue backlog | Preserve accepted durable work while exposing freshness degradation. | Slow noncritical producers, bound retries, and isolate poison work from the main queue. | Oldest-message age, lag, DLQ rate, drain-rate estimate, and a peak-backlog recovery test. |
| Region unavailable | Route only to healthy, pre-provisioned capacity; declare reduced features if necessary. | State RTO, RPO, consistency impact, DNS/routing delay, and dependency locality. | Regional evacuation exercise with measured capacity, data convergence, and rollback. |
| Bad deployment | Halt the canary and restore the last compatible code, schema, and configuration. | Limit blast radius and avoid a rollback that cannot read forward-written data. | SLO burn correlated with change events; rollback-time and compatibility rehearsal. |
Interview close: leave a decision ledger, contract sheet, capacity sheet, failure matrix, observability plan, and open-risk register. “Exactly once” is useful only after naming the source, processing boundary, destination, and replay behavior.
Examples: one local payment intent per scoped key; one external charge only with provider idempotency plus uncertain-outcome reconciliation; no negative sellable inventory; ordered messages within one conversation. Then choose the smallest transaction or consensus boundary that protects each claim.
Bound queues, shed optional work, reserve critical capacity, and return a deliberate response. An unbounded queue converts overload into memory pressure and unusable tail latency.
Record durable intent, make consumers duplicate-tolerant, quarantine poison work, reconcile derived views, and prove that failover cannot expose two owners without fencing.
For each major decision name an SLI, load or fault test, saturation threshold, alert, rollback signal, and capacity owner. “Highly available” is not measurable until the request contract is defined.
11 · Interview practice arena
Choose a prompt, work through each checkpoint aloud, and reveal the coaching notes only after committing to an answer.
Users submit a long URL and receive a short link. Opening the short link redirects quickly and reliably.
Ask questions before drawing. Separate core requirements from optional features.
Use round numbers to expose the likely bottleneck and storage shape.
Name the contract and source of truth before adding infrastructure.
Explain one write and one read end-to-end. Keep the first design simple.
Let the workload choose the deep dive: hot keys, ordering, fan-out, delivery, or consistency.
Summarize decisions, failure behavior, observability, security, and the next scaling step.
Follow-up pressure test
Identify the first saturated resource. Scale that component—not everything.
State failover behavior, recovery objective, and consistency impact.
Prevent a single key, partition, or user from concentrating load.
Define idempotency keys, deduplication window, and safe retries.
Use deadlines, bounded retries, circuit breaking, and graceful degradation.
Add authentication, quotas, rate limiting, validation, and audit signals.
12 · Deliberate study path
Use interview material for structure, foundational books for depth, and open repositories for repetition.
Framework, estimation, and approachable designs such as rate limiting, URL shortening, feeds, chat, and storage.
Official overview ↗Free topic summaries, trade-offs, interview questions, sample solutions, diagrams, and Anki decks.
GitHub repository ↗Updated coverage of reliability, scalability, data models, storage, replication, partitioning, transactions, streams, and modern distributed-data practice.
Official 2nd-edition page ↗Availability, latency, capacity, monitoring, incident response, error budgets, and reliable production practice.
Read online ↗A broad free index spanning fundamentals, networking, APIs, databases, distributed systems, and case studies.
GitHub repository ↗Deeper bottlenecks and trade-offs across queues, metrics, payments, object storage, maps, email, and exchanges.
Official overview ↗The IETF standards for methods, status codes, validators, conditional requests, freshness, shared caches, and cache-control behavior.
RFC 9110 semantics ↗RFC 9111 caching ↗John Little’s foundational result connecting average arrival rate, time in a boundary, and average work in that boundary.
INFORMS paper ↗The extended Raft paper covering leader election, replicated logs, safety, membership changes, and the assumptions behind a consensus group.
Raft paper ↗Google’s paper on synchronous replication, external consistency, automatic sharding, and explicit clock uncertainty at global scale.
Google Research paper ↗Operational guidance on timeout selection, retry amplification, token budgets, exponential backoff, and breaking correlated retry storms.
AWS Builders’ Library ↗