Requirements and Scope
Turn a one-line prompt into functional and non-functional requirements, ask the questions that change the design, and rank the answers into priorities.
On this page
A candidate is asked to design a restaurant reservation system. They build a fast, well-cached search for open tables and a booking endpoint behind it. Thirty minutes in, the interviewer asks: "Two diners just booked table 7 for 19:00 on Friday. Who gets it?" The cache-first design has no answer, and there is no time left to rebuild the write path.
One question in the first five minutes would have saved it: "Is it ever acceptable to double-book a table?" Requirements decide which parts of the design must be strict, which can be loose, and which you can skip.
Two kinds of requirement
Functional requirements are what the system does: the verbs a user performs. Write them as short sentences: "a diner searches for open tables by restaurant, date and party size", "a diner books a table", "a diner cancels".
Non-functional requirements are how well it must do them: latency, availability, consistency, durability and scale. They are where designs differ. Two systems with the same features can need completely different architectures because one must never lose data and the other must answer in 50 ms.
A third list matters as much: out of scope. Saying "I'll leave out payments and reviews" buys you time for the parts that carry signal, and the interviewer can still pull something back in.
The questions that change the design
Ask in this order: features, then scale, then quality. Each question earns its place only if a different answer would change what you build.
- Who uses it, and for what? The two or three core actions. Diners search and book; do restaurants also manage their tables in our system?
- What is out? Payments, reviews, waitlists. Propose the cut yourself.
- How many? Daily users or daily actions, and the read/write ratio. This decides caching, replicas and partitioning.
- How fresh must reads be? Can search be a few seconds behind? This decides whether replicas and caches are allowed on that path.
- What must never go wrong? Double bookings, lost writes, charging twice. This decides where you need strong consistency or transactions.
- How available, and where? One country or global? Is a minute of downtime on booking acceptable?
Design a restaurant reservation system.
OK. Should it be scalable and highly available?
Sure.
And low latency? Then I'll use microservices with a cache and a message queue.
Design a restaurant reservation system.
The core flows I see are: diners search open tables by restaurant, date and party size, then book or cancel. Restaurants set up their tables. I'll leave out payments, reviews and waitlists. Does that match?
Yes. About 20 million searches and 1 million bookings a day, in one country.
So searches outnumber bookings 20 to 1. Can search results be a few seconds stale? And I assume a double booking is never acceptable.
Stale search is fine. No double bookings, ever.
Then I'll make booking strictly consistent on one source of truth, and serve search from replicas and caches. Confirmation emails can be a minute late.
From answers to priorities
Write the result where the interviewer can see it, with numbers:
- Functional: search open tables; book a table; cancel; restaurants manage tables and opening hours.
- Non-functional: no double bookings; a confirmed booking is never lost; search answers in under 200 ms and may be a few seconds stale; booking stays available at 99.9%.
- Out of scope: payments, reviews, waitlists.
Put numbers on vague words. "Highly available" means nothing; 99.9% means about 0.001 × 30 × 24 × 60 ≈ 43 minutes of downtime a month, and 99.99% means about 4 minutes. Four minutes is too short for a person to react, so 99.99% means automatic failover to a standby that is already running.
Then rank. When two requirements pull against each other, the ranking decides. Here, correctness of bookings beats booking latency, and search freshness is the first thing to give up. The diagram shows where each priority lands.
request and replyasynchronous message
Step through a search that sees stale data, and watch why it does no harm.
1A diner searches restaurant 42 for 4 people on Friday. Search may be a few seconds stale, so it reads a replica.
2The replica says table 7 is free at 19:00. It is wrong: someone booked it on the primary 0.5 s ago, and replication has not caught up. That is what replica lag means.
3The diner books table 7 at 19:00. Bookings always go to the primary, as a conditional write: reserve only if still free.
- double bookings
- 0
4The condition fails. The API answers
409 Conflictwith other free times. The stale search cost one retry, never a double booking.- double bookings
- 0
5The diner picks 19:30. The conditional write succeeds and is committed on the primary.
- double bookings
- 0
6The API publishes a
bookedevent and replies201without waiting for the email. (A crash between the commit and the publish would lose this email; data modeling shows the fix.)- double bookings
- 0
7The email worker is down. Bookings keep succeeding; events wait in the queue and the emails go out late. That matches the priority we set.
The queue figure is arithmetic, not a guess: at the peak of 50 bookings a second (5 times the average of 1 million ÷ 100,000 = 10), one minute of outage queues 50 × 60 = 3,000 emails.
When you cannot get an answer
Sometimes the interviewer says "you decide". It tests judgment. There are three ways to handle unknowns.
| Option | Good at | Bad at | Pick it when |
|---|---|---|---|
| Ask everything up front | Nothing is missed. | Ten minutes of questions and no design. Looks like stalling. | Never as a habit. Only when the prompt is truly unfamiliar. |
| Assume silently | Fast. | The interviewer cannot correct a wrong assumption they never heard. | Never. |
| Ask the few that matter, state the rest Usual default | Fast, and every assumption is visible and correctable. | You may pick an assumption the interviewer then changes; adapt when they do. | Almost always. Ask 4 to 6 questions, then say "I'll assume X unless you'd like otherwise." |
In the interview
Spend about 5 minutes here, as in the framework. Phrases that show judgment:
- "The core flows I see are X, Y and Z. I'll leave out A and B. Does that match what you want?"
- "Is it ever acceptable to [double-book / lose a message / show a stale price]?"
- "Reads outnumber writes 20 to 1, so the read path is the one to optimize."
- "I'll assume one country. If it were global, the booking path would change most."
Follow-ups you should expect:
- "Why not make search strongly consistent too?" Every search would read the primary: 1,000 reads a second at peak (20 million ÷ 100,000 = 200 on average, times 5) on the one machine that must stay fast for bookings. Staleness costs a rare 409, which is cheap.
- "The primary dies just after confirming a booking. Is it lost?" With async replication it can be, which breaks "never lost". So the commit waits for one synchronous standby before the API returns 201. That adds a few milliseconds to each booking, which the ranking allows.
- "What if the restaurant overbooks on purpose?" That is a new functional requirement (a per-restaurant overbooking limit). It changes the condition on the write, not the architecture.
- "Now it's global." Search can be served from every region. Booking for a given restaurant still needs one place that decides, normally in or near the restaurant's region.
Common mistakes
Which of these is a non-functional requirement?
The interviewer wants booking 99.99% available instead of 99.9%. About how much downtime a month does that allow?
A search read from a replica shows a table as free, but it was booked a moment ago. What should the booking request do?
What to practice next
Turn the scale answers into rates and bytes in Back-of-the-Envelope Estimation. For a case where consistency on one path decides the design, see Design Ticket Booking.