System Design Fundamentals · Foundations
Functional vs. Non-Functional Requirements
Every system has two categories of requirements, and conflating them is the single most common reason a design goes sideways under questioning.
| Type | Answers | Example |
|---|---|---|
| Functional | What should the system do? | "Users can post a message up to 280 characters." |
| Non-functional | How well must it do it? | "p99 read latency under 200ms at 50K reads/sec." |
Functional requirements are usually easy to gather — they're the feature list. Non-functional requirements are where the actual design work happens, because they determine which trade-offs you're allowed to make. The standard set to pin down for almost any system:
- Latency — what's the acceptable response time, and at which percentile? (p50 is what most users feel; p99 is what your on-call feels.)
- Throughput — requests per second, at peak, not average.
- Consistency — does a write need to be immediately visible everywhere, or is "eventually" acceptable? (Chapter 3 covers this in depth.)
- Availability — what's the tolerable downtime? "Three nines" (99.9%) is ~8.7 hours/year; "five nines" is ~5 minutes/year — a wildly different engineering budget.
- Durability — can you ever afford to lose data once it's acknowledged as written?
A concrete example
Take "design a URL shortener." The functional requirements are almost trivial: given a long URL, return a short one; given a short one, redirect to the long one. The entire design difficulty lives in the non-functional side:
Reads : Writes → ~100:1 (shortening happens once, redirects happen constantly)
Latency → redirect must feel instant (sub-50ms)
Consistency → eventual is fine (a few seconds' delay before a new short link
resolves everywhere is imperceptible to users)
Availability → high — a broken redirect service breaks every link using it
That single table already tells you the shape of the solution: heavily read-optimized, cache-friendly, and not a system that needs strong consistency — which rules out an entire category of "safe-sounding" but wrong designs (e.g. a strongly-consistent distributed transaction on every redirect) before you've drawn anything.