Clarifying requirements
The interview starts with the design you don't draw. Split functional from non-functional requirements, name the core entities and read/write access patterns, and pin consistency, latency, and availability targets — those constraints, not the boxes, decide the architecture.
A candidate hears “design Twitter” and is drawing boxes within thirty seconds: a load balancer, an app tier, a database. Ten minutes later the interviewer asks, “How do you keep a celebrity’s 100M-follower timeline fresh?” — and the whole design collapses, because it was never built to answer that. The candidate solved a problem nobody had specified. The strong candidate, given the same three words, spent the first five minutes not drawing anything: Who posts and who reads? Is the timeline real-time or eventually consistent? Are we designing posting, the timeline, search, or all three? They were not stalling. They were deciding which system to build before building it.
The design you don’t draw
A system-design interview is not a test of how many components you can name. It is a test of whether you build the right system — and “right” is defined entirely by requirements the interviewer will not volunteer. The opening prompt (“design a chat app,” “design a ride-share”) is deliberately under-specified, the way a real product brief is. The first move of a senior engineer is the same in the interview and in a design doc at work: refuse to commit to a structure until the problem is scoped.
This matters because the architecture is downstream of the constraints, not the features. “Design Twitter” with a 10-second staleness budget and “design Twitter” with a strict-real-time budget are two different systems — one can fan out on write and cache aggressively, the other cannot. You cannot draw the second box correctly until you know which one you’re in. Skipping requirements is the single most common reason a strong technical candidate fails the interview: they build something impressive that answers the wrong question.
Functional vs non-functional
Split requirements into two piles, because they constrain the design in different ways. When you skip this split, you’ll find yourself fifteen minutes deep in a cache design before realizing you haven’t agreed whether the data even needs to be durable.
Functional requirements are what the system does — the features, stated as verbs the user performs. For a URL shortener: create a short link, redirect a short link to its target, optionally show click analytics. They define the API surface and the entities. Get these wrong and you build the wrong product.
Non-functional requirements are how well it must do it — the qualities, stated as numbers and targets. Scale (how many users, what QPS), latency (p99 budget), availability (the SLO — see the availability unit), consistency (strict or eventual), durability (can we ever lose data), and cost. Get these wrong and you build the right product in a shape that can’t survive contact with production.
The trap is treating the interview as purely functional (“it lets you post and read”). Functional requirements are usually easy and shared by every candidate. The non-functional requirements are where the design is actually decided, and where the interviewer is watching to see if you know it.
▸Why this works
Why do non-functional requirements dominate? Because two systems with identical features can have wildly different architectures once the targets change. A “design a key-value store” that tolerates eventual consistency and 5-minute staleness is a cache; the same prompt demanding linearizable reads and zero data loss is a consensus-replicated database with very different cost and latency. The features (“get”, “put”) are identical — but durability, consistency, and latency targets push you from one box diagram to a completely different one. This is the same lesson as CAP/PACELC from the data-distribution unit: you don’t choose your guarantees freely; you trade them, and the requirements tell you which trade you’re allowed to make.
Scope to what matters
The under-specified prompt is also too big. “Design YouTube” contains upload, transcoding, storage, the recommendation feed, search, comments, monetization, and live streaming — each a multi-week design on its own. You cannot design all of it in 45 minutes, and trying signals that you can’t prioritize.
So you scope, out loud, and you let the interviewer steer. State the candidate features, propose which one or two are the interesting core, and confirm: “There’s upload, playback, recommendations, and search here. I’d focus on upload-and-playback at scale, since that’s where the storage and delivery challenges are — does that match what you want to dig into?” This does three things: it shows you can identify where the difficulty lives, it gives the interviewer a chance to redirect to the part they care about, and it bounds the problem so the rest of the session is deep instead of shallow-everywhere. A scoped design you take deep beats a complete design you take nowhere.
Core entities and access patterns
What entity does this system actually store — and how does anything read or write it? If you can’t answer that before drawing boxes, the boxes will be wrong.
Once scoped, name the core entities — the nouns the system stores. For a ride-share: Rider, Driver, Trip, Location. For a chat app: User, Conversation, Message, Membership. This is a small list (usually 3–6), and it is the seed of your data model. Naming them early forces clarity about what state actually exists.
Then — and this is the move most candidates skip — characterize the access patterns: for each entity, how is it read and written? Read-heavy or write-heavy? By what key? In what shape (a single lookup, a range scan, a join, a fan-out)? Hot keys or uniform? This is the most load-bearing question you can ask, because it determines your storage and indexing decisions before you’ve drawn a single box.
entity write pattern read pattern ratio
─────────────────────────────────────────────────────────────────────────────
Message append, by conversation range scan, recent-first write ≈ read
Timeline fan-out on new post single read, by user, hot read >> write (100:1)
Trip create + status updates lookup by id, geo-query open write-ish, low volumeA timeline that is read 100× more than written wants a precomputed, cached read path; a write-heavy event log wants an append-optimized store. The access pattern, not the entity, picks the database. This is where the scalability unit’s back-of-envelope reflex pays off: the read/write ratio plus the QPS estimate is what turns “we need a database” into “we need this kind of database.”
State the targets as numbers
Vague non-functional requirements are worthless. “It should be fast” and “it should be highly available” don’t constrain anything. Convert each to a number you can design against:
- Latency: a p99 budget, not an average (the latency-vs-throughput lesson — the mean hides the tail). “Reads p99 ≤ 100 ms, writes can be slower.”
- Availability: an SLO with its error budget (the SLA/SLO/SLI lesson). “99.9% — about 43 minutes of downtime a month.”
- Consistency: pick a point on the spectrum and say why. “Posts must be read-your-writes for the author; other users tolerate a few seconds of staleness.” That single sentence licenses caching and async fan-out — or forbids it.
- Scale: the numbers that change the design (next lesson). Daily active users, QPS, data growth over years.
Together, these four numbers fully pin the design space: without a latency target you can’t justify a cache; without a consistency choice you can’t decide whether fan-out is even allowed. Stating them out loud is not pedantry — each number is a lever that turns one architecture on and another off, and naming them is how you and the interviewer agree on which system you’re actually building. When you find yourself stating a target as a vague adjective (“fast,” “reliable”), stop and replace it with a number — the architecture hasn’t been decided yet.
▸Common mistake
The most expensive requirements mistake is inventing constraints the interviewer didn’t ask for — usually over-engineering. The candidate hears “design a link shortener for an internal tool” and immediately designs for a billion QPS, global multi-region replication, and strict consistency, burning the whole session on machinery the problem never needed. Gold-plating is as much a failure as under-scoping: it shows you can’t right-size a solution to its constraints. The fix is the same discipline in reverse — ask for the scale rather than assuming the largest one, and design for the requirement you were given, with a sentence about how it would change at 100×. Build for the problem in front of you, not the most impressive problem you can imagine.
You're asked to 'design a chat app.' Which question most changes the architecture and should be asked first?
For a social timeline, reads outnumber writes ~100:1. What does this access pattern most directly justify, before you've drawn any box?
Two requirements piles constrain the design differently: _______ requirements are what the system does (the features, as user verbs), while non-functional requirements are how well it must do it (scale, latency, availability, consistency — stated as numbers), and the latter is usually where the architecture is actually decided.
- 01What is the difference between functional and non-functional requirements, and why do the non-functional ones decide the design?
- 02Why characterize access patterns, and how do they change the design?
- 03How do you scope an over-broad prompt, and what's the failure mode at each extreme?
A system-design interview is decided in the first few minutes, before any box is drawn. Split requirements into functional (what it does — the features, as user verbs) and non-functional (how well — scale, p99 latency, availability SLO, consistency, durability, cost, stated as numbers), and remember the non-functional targets are where the architecture is actually chosen: identical features can demand completely different systems once the targets move (a lossy eventually-consistent store is a cache; a linearizable, durable one is a consensus database — the CAP/PACELC trade from the data-distribution unit). Scope the over-broad prompt out loud and let the interviewer steer toward the interesting core — a scoped design taken deep beats a complete one taken nowhere. Name the 3-6 core entities and, crucially, their read/write access patterns, because the access pattern (not the entity) picks the storage and the read path — a 100:1 read-heavy timeline wants a precomputed, cached read path. And state every target as a number you can design against. The two failure modes are symmetric: under-scoping solves the wrong problem, and gold-plating builds machinery the problem never needed — both are a failure to right-size a design to its constraints. Now when you hear a vague prompt, your first move is to stop, ask the four kinds of questions, and write the constraints before drawing any box.
Practice
Start at the top. Tasks go easiest → hardest: recall a fact, apply it to a case, then a senior-level stretch. Open one, attempt it, then reveal.
Something unclear?
Ask a question about this lesson. Questions are anonymous and go straight to the author to make the lesson better.
Apply this
Put this lesson to work on a real build.