Functional vs Non-Functional Requirements
Functional requirements describe what the system must do: park a car, issue a ticket, transfer money.
Introduction
Functional requirements describe what the system must do: park a car, issue a ticket, transfer money. Non-functional requirements (NFRs) describe how well: latency, throughput, consistency, availability, security.
In LLD interviews, functional requirements drive your class model. NFRs drive threading, locking, caching, and interface granularity — often the difference between a pass and a strong hire.
Learning to elicit both types separates candidates who draw rectangles from those who design systems interviewers trust in production.
Understanding the topic
Key concepts
- Functional: features, business rules, inputs/outputs, error behavior.
- Non-functional: performance, scalability, reliability, maintainability, security.
- NFRs may be implicit — 'multiple users booking same seat' implies concurrency.
- Traceability: each use case maps to functional reqs; each NFR maps to design tactics.
- MoSCoW prioritization helps when time is limited (Must/Should/Could/Won't).
- Conflicts: strong consistency vs availability — state assumptions explicitly.
Step-by-step explanation
- Ask what operations users and admins must perform.
- Probe scale: users, QPS, data size, geographic distribution.
- Ask about consistency: can two users get the last seat?
- Identify security: authentication, authorization, audit logs.
- Map functional reqs to classes; map NFRs to locks, queues, caches, replicas.
- Document deferred requirements to show scope control.
Informative example
Functional requirement: unique seat booking. NFR: thread-safe under concurrent requests:
public final class SeatBooker {private final Map<String, Set<String>> showSeats = new ConcurrentHashMap<>();public boolean book(String showId, String seatId, String userId) {Set<String> taken = showSeatsFor(showId);return taken.add(seatId); // false if already booked}private Set<String> showSeatsFor(String showId) {return showSeats.computeIfAbsent(showId, id -> ConcurrentHashMap.newKeySet());}}
ConcurrentHashMap.newKeySet() gives atomic add per seat — tie functional uniqueness to an NFR without over-engineering distributed locks in a single-JVM LLD.
Real-world use
Real-world applications
- Clarifying interview prompts before drawing classes.
- Writing acceptance criteria for LLD-derived modules.
- Architecture review checklists.
Best practices
- Convert vague NFRs to numbers when possible ('fast' → '<200ms p99').
- Separate user-facing functional reqs from admin/reporting reqs.
- Flag NFRs that need HLD (multi-region) vs LLD (synchronized block).
- Use examples: 'VIP vehicle gets spot X' is functional.
- Revisit NFRs after class diagram — missing audit log? add AuditRecorder.
Common mistakes
- Ignoring 'multiple users' and designing single-threaded singletons.
- Implementing distributed cache when interviewer assumed single process.
- Treating all reqs as must-have — no time left for core design.
- Confusing business rules with infrastructure choices.
Advanced interview questions
Q1BeginnerGive an example of a functional requirement.
Q2BeginnerGive an example of a non-functional requirement.
Q3IntermediateHow do NFRs affect LLD?
Q4IntermediateWhat if functional and NFR conflict?
Q5AdvancedHow would you gather reqs in a 45-minute interview?
Summary
Functional = behavior; non-functional = quality attributes. Both shape LLD — classes for features, tactics for NFRs. Probe concurrency, scale, and failure explicitly. Prioritize must-have use cases when time is tight. Document assumptions and deferred scope.