Senior Engineering Interview Handbook / Chapter 76
Requirements and Non-Functional Requirements
A practical method for discovering functional and non-functional requirements, ranking competing constraints, controlling scope, and revising the design contract when the prompt changes.
Preparing audio…
Audio edition
Requirements and Non-Functional Requirements
Page tools
A product name is not yet a problem
“Design a calendar” gives you almost nothing to design. You could build a personal reminder tool, a shared team calendar, a room-booking service, or an enterprise system with residency and audit obligations. All four have events and users. They do not have the same correctness boundary, privacy model, or failure cost.
Asking for the number of users does not repair the ambiguity. Ten million users of personal reminders may be an easier correctness problem than ten thousand people competing for scarce operating rooms. Scale acts on a product promise; it cannot supply one.
The opening of a system-design interview therefore has a precise job: discover which promise the system must keep, choose the smallest useful slice of that promise, and identify the failures that the architecture must prevent. The result should fit in a few lines. You will need to carry it through estimates, APIs, data ownership, failure handling, and the final summary.
Find the question that divides the designs
A long questionnaire spends the opening without necessarily reducing ambiguity. Look instead for hinge questions: questions whose answers would send the architecture down meaningfully different paths.
For the calendar prompt, a useful first question is:
Are we designing shared team scheduling, reservation of scarce resources, or enterprise calendar management? Resource booking introduces a hard conflict rule, while enterprise use may make privacy, audit, and regional placement central.
The explanation is part of the question. It shows the interviewer why the answer deserves time. Once the interviewer chooses shared team scheduling, you can ask about the core workflow and its harm:
Should a user be able to create an event, invite colleagues, see free/busy availability, and receive changes? Of those flows, what would be most damaging to get wrong: losing an acknowledged edit, exposing private event details, or delivering a notification late?
That question distinguishes correctness from convenience. Suppose the answer is that acknowledged edits must survive, private details must not escape, and notifications may trail the event by several seconds. You now know more about the architecture than “highly available and scalable” could tell you.
Other prompts have different hinges. A feed design may divide on whether freshness or ranking quality dominates. A payment system may divide on who owns the ledger and when a charge becomes final. A file service may divide on object size, sharing policy, and retention. The method is stable; the questions are not.
Leave clarification when you can name the product variant and the harm most likely to bend the design. You do not need every product decision before proceeding.
Write a promise, not a feature inventory
Functional requirements are observable behavior. “Users, calendars, invites, and notifications” is a list of nouns; it says nothing about the transitions or permissions the system must support. For shared team scheduling, a useful first slice is:
- a member can create, change, cancel, and read an event;
- an organizer can invite participants, and each participant can change their response;
- an authorized member can see another member’s free/busy intervals without seeing private event details;
- relevant participants eventually receive notification of a material event change; and
- a calendar owner can change membership and permissions.
These verbs reveal state transitions, read and write paths, authorization, derived views, and asynchronous work. They are enough to support a serious design.
They also leave real features out. Advanced recurrence, external calendar sync, offline editing, scheduling suggestions, billing, and room optimization could each consume the rest of the interview. Excluding them is sound only if the retained slice still contains the prompt’s central difficulty. A candidate who excludes permissions from a shared calendar has made the system smaller by removing its reason to exist.
State the cut in a way that permits redirection:
I’ll design shared event lifecycle, invitations, free/busy views, permissions, and change notifications. I’ll defer advanced recurrence, external sync, and offline editing unless you want one of those as the deep dive.
Scope is now an explicit decision rather than a trail of features that happen not to appear on the diagram.
Turn qualities into claims about failure
Non-functional requirements are often introduced as a catalog: availability, durability, consistency, latency, throughput, privacy, compliance, regionality, accessibility, maintainability, and cost. The names are useful for memory. They become design inputs only when they say which behavior must survive which pressure.
Consider durability. “The system should be durable” is ceremonial. “After an event change is acknowledged, the canonical event and the audit-worthy facts needed to explain that change must survive a process failure” identifies an acknowledgement boundary and durable state. Notification fan-out can occur after that boundary; it should not decide whether the edit exists.
Consistency must name a fact and an observer. The organizer should read their own acknowledged change. A participant’s calendar view may lag briefly. An RSVP count can be a derived value. If the product later includes room booking, two successful reservations for the same room and time must not coexist. One word—“consistent”—cannot express all four rules.
Latency and throughput also belong to paths, not to the system in general. Opening a calendar and saving an edit are interactive. Sending thousands of notifications is background work and can be batched or coalesced. The next chapter will estimate the actual volumes; at this stage, the useful discovery is that user-facing writes and fan-out do not need the same latency budget.
Availability asks what the product should still do during failure. Read-only calendar access might continue while event creation is temporarily blocked. Notification delivery might pause and catch up. If stale permissions could expose a private event, serving an old response may be worse than refusing the read. “Always available” hides these choices.
Privacy is similarly concrete. A free/busy response should reveal intervals, not titles or attendee lists. Cache keys, logs, search indexes, notifications, and analytics must preserve that projection. If the interviewer adds data residency, deletion, or audit obligations, identify the affected data and operation; do not use “compliant” as a substitute for a rule. Regionality may constrain placement even when a nearby replica would reduce latency.
Accessibility changes the functional contract when the core workflow cannot depend on a visual calendar grid alone. The underlying operations need usable textual descriptions, ordered focus, and conflict messages that communicate more than color. This is not a decorative requirement to mention after the architecture.
Maintainability and cost deserve the same discipline. Separating recurrence or external sync behind a clear boundary may keep change from corrupting the canonical event model. Coalescing repeated notifications may bound fan-out cost. Tenant limits may protect the service from one organization’s accidental or abusive workload. Choose such constraints when they alter the design, not because the category exists on a memorized list.
Make the priorities audible
Real requirements compete. Privacy-aware reads can reduce cache reuse. Durable acknowledgement adds work to the write path. Regional placement can increase coordination latency. Fresher derived views consume more compute and fan-out capacity.
Do not promise to maximize everything. Rank the constraints and name the relaxation you are buying:
For this version, I will protect acknowledged event changes and private details. Calendar views should reflect changes quickly, but they may be briefly stale, and notifications may arrive later. That lets the canonical write complete before derived views and fan-out, without weakening the privacy rule.
The sentence is provisional, not evasive. It gives the first architecture a direction while leaving a clear place for the interviewer to object.
At this point the working contract can remain small:
PROMISE
Team members can coordinate shared events without losing acknowledged changes
or exposing private event details.
IN SCOPE
Event lifecycle; invitations and responses; free/busy; membership and
permissions; change notifications.
PROTECT
Canonical event durability; authorization; privacy-preserving projections.
RELAX
Calendar views may be briefly stale; notifications are asynchronous.
DEFER
Advanced recurrence; external sync; offline editing; room optimization.
OPEN
Expected scale, regional use, retention, and the interviewer’s preferred deep dive.
This is not meeting notes. It is the argument that later choices must satisfy.
Let the contract choose the first boundaries
The contract already implies an order of work. Model canonical event state and its authorization before designing notification delivery. Treat free/busy as a privacy-preserving projection rather than a second copy of full event data. Complete an acknowledged write at a durable boundary, then update derived views and enqueue notifications. Make notification handlers idempotent because retries should not produce duplicate user-visible effects.
None of those statements selects a database or queue product. Each narrows the job that a component must perform. The later architecture may change, but it can no longer be a generic collection of services.
This is how the requirements conversation might sound as it hands off to estimation:
Interviewer: Design a collaborative calendar.
Candidate: Is the central product team scheduling or resource booking? Booking
adds a strict conflict rule, so I want to keep the variants separate.
Interviewer: Begin with team scheduling.
Candidate: I’ll include event changes, invitations and responses, free/busy,
permissions, and notifications. I’ll protect acknowledged edits and private
details. Views can be briefly stale, and notifications can lag. Before I model
the data, I’d like to estimate active calendars, peak event changes, and
notification fan-out because those numbers could change the derived-view and
delivery design.
The candidate has not delayed architecture. They have made the first architecture decisions explainable.
When the prompt changes, revise the promise first
Now the interviewer adds room booking. It is tempting to append a room service to the diagram and continue. But the new fact changes the product contract.
For ordinary team events, two people can create overlapping meetings. For a room, overlapping successful reservations violate the meaning of “reserved.” Free/busy staleness is no longer enough to reason about the write path: two clients might both observe an empty interval. The design needs an authoritative reservation operation that makes the conflict check and the write one indivisible decision at the relevant resource boundary.
Say what changed:
Room booking strengthens one requirement. Calendar views may still be derived and briefly stale, but reservation acceptance must be serialized or conditionally committed for a room and interval. I’ll add rooms and reservations to the functional slice, make conflict prevention a protected invariant, and revisit the write model. Notifications remain asynchronous.
The distinction prevents a common overcorrection: making every calendar read and RSVP strongly consistent because one operation needs conflict prevention. Requirements can apply to a particular fact or path.
A different interruption should reopen a different decision. If tenants must keep event data in an assigned region, revisit ownership, replication, failover, and cross-region collaboration. If external sync becomes central, revisit idempotency, conflict representation, rate limits, and the source of truth. If the product must work offline, revisit identity, versioning, merge behavior, and what “acknowledged” means. Do not bolt a new constraint onto the end; return to the earliest promise it invalidates.
Rehearse the judgment, not the checklist
Requirements practice is useful on its own, before a full architecture mock. Take six minutes with each of these prompts:
- Design group chat. Separate private groups, enormous public channels, and regulated workplace messaging. Choose one, then name the message property you will protect and one behavior you will relax.
- Design file sharing. Choose whether the hard problem is large-object transfer, collaborative permissions, or governed retention. Write the first functional slice without naming components.
- Return to the calendar contract. Add offline editing, room booking, or regional residency. Identify the earliest line that becomes false and revise only the affected design decisions.
Review the result by replaying it through the proposed architecture:
- Can another person tell which product variant you chose?
- Are the functional requirements observable behaviors rather than nouns?
- Does each dominant non-functional requirement name a path, failure, or boundary?
- Have you stated what may be stale, delayed, unavailable, rebuilt, or lost?
- Did the exclusions preserve the prompt’s central technical difficulty?
- Can every major component point back to a requirement, and can a changed constraint lead you to the decision it invalidates?
If you cannot answer the last question, the requirements are probably labels rather than a contract.
Field reference
REQUIREMENTS PASS
VARIANT
Which version of the product changes correctness, privacy, scale, or operations?
PROMISE
Who performs the core flow? What harm must the system prevent?
FUNCTIONAL SLICE
Choose a few observable behaviors: actor + action + important outcome.
PRESSURE
For each dominant quality, name the path, failure, boundary, and consequence.
What must be durable, fresh, private, available, local, accessible, or bounded?
PRIORITY
I will protect X, optimize Y, and allow Z to relax because...
SCOPE
Keep the central difficulty. Defer adjacent product complexity explicitly.
REVISION
When a constraint changes, update the earliest promise and design choice it breaks.
The requirements pass is complete when the next decision has something to obey. The immediate next decision is usually which numbers matter. Chapter 77 uses the contract to estimate pressure rather than perform disconnected arithmetic.
Related reading: The System-Design Interview Framework places this work on the round’s clock, and Communicating Trade-Offs Like a Senior Engineer develops the language for stating priorities and revision.
Continue reading
Full table of contents