The system design interview

An open-ended hour with a whiteboard. The score comes from requirements, numbers and named trade-offs, not from naming technologies.

Short answer

A system design interview gives you a deliberately vague prompt, such as design a link shortener or a news feed, and 45 to 60 minutes to turn it into a design. You are scored on how you pin down requirements, estimate scale, choose a data model and an API, and then name the trade-offs your choices force. The strongest signal you can give is a specific trade-off stated before the interviewer asks for it.

Last reviewed October 13, 2026

What the system design round tests

Coding rounds ask whether you can solve a closed problem. Design rounds ask whether you can take an ambiguous one and make it tractable. There is no correct answer; there are defensible answers and indefensible ones.

Four behaviours carry the score. Requirements discipline: you turn one sentence from the interviewer into a short list of functional requirements and a shorter list of constraints before you draw anything. Quantitative reasoning: you convert users into requests per second, bytes per day and rows per year, with rough arithmetic out loud. Structural clarity: your diagram has components with a single purpose each, and data flows you can trace end to end. Trade-off reasoning: you say what each choice costs, which is where senior candidates separate themselves.

What does not score is a list of product names. Saying you would use a queue, a cache and a document store means nothing until you say what goes in each, what happens when one is unavailable, and why the simpler design was not enough.

Keep the level honest too. For a junior role, one service with a relational database and a clear API is a complete answer. For a senior role, the interviewer keeps adding load, failures and conflicting requirements until something in your design has to give. That escalation is the test, not a sign that you are failing.

A framework you can run in 45 minutes

Use the same seven steps every time, out loud, and keep an eye on the clock.

Start with functional requirements, five minutes at most. Ask what the system must do, for whom, and what is out of scope. Write the list where the interviewer can see it and get agreement.

Then non-functional requirements. Which matters more, availability or consistency? What latency is acceptable at the ninety-ninth percentile? How much data, kept for how long? Is the workload read heavy or write heavy? That last answer shapes most of what follows.

Third, estimate. Pick round numbers and do the arithmetic aloud: daily active users, actions per user per day, divided into seconds for an average rate, multiplied for peak. Then size one record and project a year of them. Precision is not the point; working in orders of magnitude is.

Fourth, define the interface: two or three endpoints or message schemas with the fields that matter. This forces the data model and often exposes a missing requirement.

Fifth, choose the data model and the store, with a reason tied to your access patterns rather than to fashion.

Sixth, draw the high level design: clients, an entry point, the services, the stores, the asynchronous paths. Trace one read and one write end to end.

Seventh, find your own bottleneck. Name the component that fails first under your estimated load, then describe the fix and its cost. Finish by summarising the decisions you would revisit with more information.

A worked prompt: a link shortener

Here is the shape of a strong first ten minutes on the most common prompt of all.

Requirements: create a short code for a long URL, redirect a visitor from the short code to the original, let the owner see how many times it was used. Out of scope: editing links, user accounts, custom branded domains. Reads vastly outnumber writes, and a redirect must be fast; analytics can lag by minutes.

Estimates: suppose 100 writes per second and 10,000 reads per second at peak, with a 500 byte record. That is roughly 3 billion new links a year and about 1.5 terabytes of link rows, which fits comfortably on one well-indexed database with room to spare, so the interesting problem is read throughput rather than storage.

Interface: a POST that takes a URL and returns a code, a GET on the code that returns a redirect, and a GET for the owner’s counts. The write endpoint should be idempotent for the same URL and owner, which is worth saying early because it removes a whole class of duplicate-handling questions.

Key generation: a random code checked for collisions, a counter encoded in base 62, or a truncated hash of the URL. Say the trade-off. Counters are compact and avoid collisions but leak volume and need coordination across writers; random codes need a uniqueness check on insert; hashes deduplicate naturally but collide more as volume grows.

Read path: the code to URL mapping is immutable once created, which is the most useful property of this design. Aggressive caching is therefore safe, and a cache in front of the store absorbs almost all of the read load.

Write path for analytics: do not increment a counter row on every redirect. Emit an event, aggregate asynchronously, and accept that the owner’s number is eventually consistent. Saying that, and noting that the requirement allows it, is the sort of trade-off the round looks for.

Caching, and the questions that follow it

Caching appears in nearly every design, and interviewers probe it because candidates tend to say “add a cache” without saying where, for how long, or what happens when the data changes.

Start with the layer you can describe precisely. MDN’s HTTP caching guide explains that Cache-Control max-age specifies freshness as an elapsed time rather than a date, so with max-age=604800 a response younger than a week is fresh and an older one is stale, and that max-age is preferred when both Expires and max-age are present. It also notes that an intermediate cache can report how long it has stored a response through the Age header, so a client can work out the remaining freshness.

The second thing to get right is who may store the response. MDN distinguishes private caches, tied to one client such as a browser, from shared caches that sit between client and server, and it warns that personalised content must be marked with the private directive if it should only be kept in a private cache. It also cautions that the presence of a cookie does not by itself make a response private.

Third, revalidation. MDN describes the ETag response header as an arbitrary server-generated value, such as a hash of the body or a version number, which the client sends back in If-None-Match so the server can answer 304 Not Modified instead of resending the body. If both If-Modified-Since and If-None-Match are present, the documentation states that If-None-Match takes precedence. One frequently misunderstood detail is worth stating in the interview: the no-cache directive does not prevent storing a response, it prevents reuse without revalidation.

With those mechanics in hand, the design questions answer themselves. Immutable, versioned assets get a long max-age and the immutable directive. Personalised pages get private. Anything derived from changing data gets a short freshness window plus a validator, and you state what stale data costs the user.

Replication and partitioning trade-offs

Once the design has more than one machine holding data, the interviewer will push on consistency and on hot spots. Both have documented answers you can quote rather than guess at.

On replication, the PostgreSQL documentation sets out the vocabulary: servers that can modify data are primaries, servers that track changes are standbys, and a standby that accepts connections and serves read-only queries is a hot standby while one that cannot be used until promoted is a warm standby. Hot standbys are therefore how you scale reads, and the documentation notes that read-only database servers can be combined relatively easily while a read and write mix is much harder, because a write to any server must propagate to all of them.

Question Synchronous replication Asynchronous replication
When is a transaction committed? Not until all servers have committed it After the primary commits, propagation lags
Data loss on failover None, per the documentation’s guarantee Some transactions might be lost
Reads from replicas Consistent whichever server is queried Possibly slightly stale
Performance A fully synchronous solution over a slow network might cut performance by more than half Minimal impact

That table compresses what the PostgreSQL manual states, and it answers the standard follow-up: which do you choose. The answer is a requirement, not a preference. Payments and ledgers justify synchronous commits; feeds, counters and search indexes usually do not, and the manual notes that asynchronous communication is used when synchronous would be too slow.

On partitioning, the question is whether your key spreads load. The DynamoDB documentation is explicit that you should design for uniform activity across all partition keys in the table and its secondary indexes, and it gives per-partition numbers: every partition is designed to deliver a maximum of 3,000 read units per second and 1,000 write units per second, where one read unit is one strongly consistent read of an item up to 4 KB, or two eventually consistent reads, and one write unit is one write of an item up to 1 KB. Item size multiplies this, so a 20 KB item consumes five read units per consistent read, leaving about 600 such reads per second on a single item.

Those numbers make the hot partition problem concrete, and the documented remedy is write sharding, which spreads one logical key across several physical ones by appending a suffix. Saying that, with the reason, is stronger than saying you would shard by user.

Common prompts, and the API design questions

A handful of prompts recur, and each one hides a different lesson. A news feed forces the fan-out decision: write time, where you push each post into followers’ feeds, against read time, where you assemble the feed on request. The honest answer is a hybrid, with the reason being accounts that have very large follower counts.

A chat system is about connection state and ordering: who holds the open connection, how undelivered messages are stored, how you order messages from clients whose clocks disagree. A rate limiter is about where the counter lives and what happens when that store is unavailable. A file or media service pushes on large uploads, chunking and serving bytes close to the user. A booking system is the one prompt where you should reach for strong consistency and a transaction, because double-selling a seat is worse than a slow page.

Some loops ask narrower API design questions instead. The recurring four are idempotency (what happens when a client retries a payment after a timeout), pagination (why cursor based beats offset based on data that changes under you), versioning (how you change a response shape without breaking existing clients), and error semantics (which failures are retryable and how a client is told). Prepare a paragraph on each; they come up in backend interviews more often than the headline prompts do.

Common mistakes, and how to prepare

The first mistake is drawing before asking. A design that answers the wrong requirements cannot be rescued in the last ten minutes, and the interviewer has usually left out something important on purpose.

The second is name-dropping. Technologies as answers invite questions you then cannot answer. Describe the property you need, pick something that has it, and say what you give up.

The third is skipping arithmetic. Candidates who never convert users into requests per second cannot tell whether their problem is one server or two hundred, and every later decision loses contact with the facts.

The fourth is designing only the happy path. Say what happens when the cache is cold, the queue backs up, a replica falls behind or a dependency times out. Pick one failure and walk through it unprompted.

The fifth is over-building. Five services, two message brokers and multi-region replication for a system with a thousand users reads as inexperience rather than ambition.

To prepare, do three things. Read primary documentation for the mechanisms you keep citing: HTTP caching, replication in a database you actually use, and the partitioning guidance for one managed store. Then design five systems end to end on paper, timed and out loud, writing down each decision with its cost. Finally, reverse-engineer a system you have really worked on, including what hurt in production. Interviewers can tell the difference between a memorised diagram and a design you have had to live with.

Practice it now

Answer out loud, as if the interviewer just asked. Then check yourself against the list.

“Design a link shortener for 100 writes and 10,000 reads per second. Begin with requirements and an estimate, not a diagram.”

Aim for 45 minutes
  • You listed functional requirements and what is out of scope, and got agreement.
  • You stated whether the workload is read or write heavy, and the latency target.
  • You did the arithmetic out loud, to an order of magnitude.
  • You defined two or three endpoints before drawing components.
  • You named your own bottleneck and what fixing it costs.
  • You described one failure path, such as a cold cache or a lagging replica.

Frequently asked questions

How long is a system design interview?

Normally 45 to 60 minutes, with one prompt that the interviewer extends as you go. Budget roughly ten minutes for requirements and estimates, twenty-five for the design, and the rest for bottlenecks and trade-offs.

Do junior engineers get system design rounds?

Sometimes, scoped to one feature rather than a whole product, and judged more gently. A single service with a relational database, a clear API and a stated bottleneck is a complete junior answer.

Should I choose synchronous or asynchronous replication in my design?

Decide from the requirement. The PostgreSQL manual notes that synchronous commits guarantee no data loss on failover and consistent reads from replicas, while asynchronous replication risks losing some transactions and returning slightly stale reads, and is used when synchronous would be too slow.

How do I avoid a hot partition?

Pick a key with high cardinality and uniform access. The DynamoDB documentation advises designing for uniform activity across partition keys, notes a per-partition ceiling of 3,000 read units and 1,000 write units per second, and documents write sharding as the way to spread one logical key across several physical ones.

Is it a problem if I do not finish the design?

No. Nobody completes a realistic design in an hour. Finishing means having traced one read and one write, named your bottleneck, and summarised the decisions you would revisit with more data.

Sources

  1. MDN Web Docs: HTTP caching
  2. PostgreSQL documentation: High Availability, Load Balancing, and Replication
  3. Amazon DynamoDB Developer Guide: Best practices for designing and using partition keys effectively