The previous chapters zoomed in: one class, one function, one pattern. A system design interview zooms all the way out. Nobody asks you to write a Strategy class; they ask you to design a news feed, a URL shortener or a rate limiter, and they watch how you reason about requirements, scale and trade-offs.

The good news is that the same habits carry over. Patterns taught you to name a problem before solving it, to isolate what varies and to prefer the smallest design that works. This chapter turns those habits into a framework you can run in 45 minutes.

What interviewers actually score

Most rubrics, whatever the company calls them, look at four things:

  1. Problem framing. Did you ask questions and pin down scope before drawing boxes?
  2. Design. Is the high-level architecture sensible, and does each component have a reason to exist?
  3. Depth. Can you go deep on one or two hard parts (data model, consistency, hot keys, failure) when asked?
  4. Trade-offs and communication. Do you say what you are giving up, and can the interviewer follow you?

Notice that "knew the right answer" is not on the list. There is rarely one right answer. A candidate who picks a simpler design and defends it clearly usually scores higher than one who draws Kafka, Cassandra and three caches without saying why.

A 45-minute framework

Minutes Step Output
0–5 Clarify requirements Functional list, non-functional targets, what is out of scope
5–10 Estimate Requests per second, storage per year, bandwidth, read/write ratio
10–15 API and data model 3–5 endpoints, core entities and their keys
15–30 High-level design Clients, gateway, services, storage, cache, queues, and the main request flows
30–40 Deep dive One or two bottlenecks the interviewer picks or you propose
40–45 Wrap up Failure modes, monitoring, what you would do next

1. Clarify requirements

Split them into two lists and say them out loud.

  • Functional: what the user can do. For a news feed: post, follow, see a feed of people I follow, newest first.
  • Non-functional: how well it must work. Daily active users, latency target (feed loads in under 200 ms at p99), availability (99.9% or 99.99%), consistency (is it fine if a post appears a few seconds late?).

Then state what you are not doing: "No ads ranking, no video transcoding, no search." Scoping is a skill being tested, not a way to dodge work.

2. Estimate on the back of an envelope

Estimates exist to drive decisions: do you need sharding, does the working set fit in memory, is bandwidth a concern. Round aggressively. A day is about 100,000 seconds (86,400), a year is about 400 days if you want easy math.

It is worth practising these numbers in code once, so the formulas stick:

type Workload = {
  dailyActiveUsers: number;
  writesPerUserPerDay: number;
  readsPerUserPerDay: number;
  bytesPerWrite: number;
  peakFactor?: number; // peak traffic relative to the daily average
  retentionYears?: number;
};

const SECONDS_PER_DAY = 86_400;

export function estimate({
  dailyActiveUsers,
  writesPerUserPerDay,
  readsPerUserPerDay,
  bytesPerWrite,
  peakFactor = 3,
  retentionYears = 5,
}: Workload) {
  const writesPerDay = dailyActiveUsers * writesPerUserPerDay;
  const readsPerDay = dailyActiveUsers * readsPerUserPerDay;
  const avgWriteQps = writesPerDay / SECONDS_PER_DAY;
  const avgReadQps = readsPerDay / SECONDS_PER_DAY;
  const storageBytes = writesPerDay * bytesPerWrite * 365 * retentionYears;

  return {
    writeQps: { avg: Math.round(avgWriteQps), peak: Math.round(avgWriteQps * peakFactor) },
    readQps: { avg: Math.round(avgReadQps), peak: Math.round(avgReadQps * peakFactor) },
    readWriteRatio: Math.round(readsPerDay / writesPerDay),
    storageTB: +(storageBytes / 1e12).toFixed(1),
  };
}

// A news feed with 10M DAU, 2 posts and 50 feed loads per user per day, 1 KB per post.
console.log(
  estimate({ dailyActiveUsers: 10_000_000, writesPerUserPerDay: 2, readsPerUserPerDay: 50, bytesPerWrite: 1_000 }),
);
// { writeQps: { avg: 231, peak: 694 }, readQps: { avg: 5787, peak: 17361 }, readWriteRatio: 25, storageTB: 36.5 }

From those four numbers you can already say something useful: reads outnumber writes 25 to 1, so the design should optimise the read path (precomputed feeds, caching), and 36 TB over five years is too much for one database node, so posts will need partitioning.

3. API and data model

Keep it short. A few endpoints and the main entities are enough to anchor the rest of the conversation:

POST /v1/posts            { text, mediaIds[] }          -> 201 { postId }
GET  /v1/feed?cursor=...  -> 200 { items[], nextCursor }
POST /v1/users/{id}/follow

Say which store holds what and what the key is: posts keyed by postId (time-sortable ID such as a Snowflake or ULID), follows keyed by (followerId, followeeId), feeds keyed by userId. Cursor pagination instead of OFFSET, because offsets get slower and skip items as new posts arrive.

4. High-level design

Draw the request path for the two or three main flows, not every box you know. For each component, say one sentence about why it is there. A typical shape:

client -> CDN (static, media)
client -> load balancer -> API gateway (auth, rate limit)
         -> post service  -> posts DB (partitioned by postId)
                          -> queue -> fan-out workers -> feed cache (per user)
         -> feed service  -> feed cache -> posts cache / posts DB (hydrate)

5. Deep dive

This is where you earn the senior signal. Pick the part where the interesting trade-off lives and go deep: how fan-out works for users with millions of followers (chapter 15), how to check "has this username been taken" for a billion users without hitting the database (chapter 16), how to keep the feed cache consistent when a post is deleted, what happens when a partition is hot.

6. Wrap up

Name the failure modes and how you would see them: queue backlog alerts, cache hit ratio, p99 latency per endpoint, a dead-letter queue for fan-out jobs that fail. Mention one thing you would build next if you had more time. Ending with a clear list beats running out of time mid-sentence.

Fifteen questions between backend and system design

Interviews for mid and senior backend roles often mix classic backend questions with system design follow-ups. These are the ones I see most, with the short answer you should be able to give before going deeper.

  1. What happens when you type a URL and press Enter? DNS lookup, TCP and TLS handshakes (or QUIC for HTTP/3), HTTP request through load balancers and proxies, server work, response, rendering. Be ready to zoom into any step.
  2. Horizontal vs vertical scaling? Bigger machine vs more machines. Vertical is simpler and has a ceiling; horizontal needs stateless services and a plan for shared state.
  3. How do you make a service stateless? Move sessions to a shared store or signed tokens, keep files in object storage, and keep no in-process state that another instance needs.
  4. Load balancing algorithms? Round robin, weighted round robin, least connections, consistent hashing for cache affinity. Chapter 6 builds a round-robin selector.
  5. SQL or NoSQL? Start from access patterns and consistency needs, not fashion. Relational for transactions and ad hoc queries; key-value or wide-column for huge, simple, partitionable access patterns.
  6. Indexes: why are reads faster and writes slower? A B-tree index is a sorted structure the database maintains on every write; it turns a full scan into a logarithmic lookup.
  7. Replication vs sharding? Replication copies the same data for availability and read scaling; sharding splits data so each node holds a part, for write and storage scaling.
  8. What is the CAP theorem really saying? During a network partition you choose between consistency and availability. Outside partitions, the everyday trade-off is latency vs consistency (PACELC).
  9. Cache strategies? Cache-aside, read-through, write-through, write-behind. Know invalidation, TTLs, and the thundering herd problem with its fixes (request coalescing, jittered TTLs).
  10. Why put a message queue between services? To absorb spikes, decouple availability, and retry work. The cost is eventual consistency and the need for idempotent consumers.
  11. At-least-once vs exactly-once delivery? Most systems deliver at least once; you get effectively-once by making handlers idempotent with a deduplication key.
  12. How do you design a rate limiter? Token bucket or sliding window counters, stored in Redis for a distributed limit, keyed by user, API key or IP, returning 429 with Retry-After.
  13. How do you handle a distributed transaction? Avoid it if you can; otherwise use a saga with compensating actions, and the outbox pattern to publish events atomically with the database write.
  14. How do you generate unique IDs at scale? UUIDv7 or ULID for sortable random IDs, or a Snowflake-style ID (timestamp, machine ID, sequence) when you need compact 64-bit integers.
  15. How do you know the system is healthy? The four golden signals (latency, traffic, errors, saturation), structured logs with request IDs, traces across services, and alerts on symptoms rather than causes.

A preparation plan

  • Weeks 1–2: fundamentals. Networking, databases, caching, queues, consistency. Answer the fifteen questions above without notes.
  • Weeks 3–4: classic problems. URL shortener, rate limiter, news feed, chat, notification system, file storage. For each one, run the full framework on paper with a timer.
  • Weeks 5–6: mock interviews. Practise out loud with a friend or record yourself. Most candidates know enough; what fails them is pacing and not stating trade-offs.

Common mistakes

  1. Drawing before asking. Five minutes of requirements saves twenty minutes of redesign.
  2. Name-dropping technology. "Use Kafka" is not a design. "Use a durable log so fan-out workers can replay after a crash" is.
  3. Ignoring the numbers you just estimated. If you computed 17,000 reads per second, the design should show where those reads land.
  4. Going wide instead of deep. Covering twenty components shallowly loses to covering eight and going deep on two.
  5. Treating it as a test, not a conversation. Check in with the interviewer: "I can go deeper on fan-out or on storage, which is more interesting to you?"

Exercises

  1. Run estimate() for a chat app with 50M DAU, 40 messages sent and 200 read per user per day, 200 bytes per message. Which numbers change your design compared to the news feed?
  2. Design a URL shortener end to end using the six steps and a 45-minute timer. Write down your trade-offs at the end.
  3. Pick three of the fifteen questions and explain each in two minutes out loud, then again in thirty seconds.
  4. Take the news feed design above and list three failure modes and the metric that would alert you to each.