Skip to content
SparkTime, home
System Design From Zero to Interview-Ready
Lessons
1 · System Design Foundations
2 · APIs and Communication
3 · Capacity Estimation
4 · Core Building Blocks
5 · Databases
6 · Distributed Systems
7 · Reliability and Operations
8 · Architecture and Security
9 · Interview Method and Foundation Case Studies
10 · Real-World Case Studies
11 · Large-Scale Case Studies
12 · Interview Readiness
Lesson 2 of 45

Lesson 2 · System Design Foundations

Functional and Non-Functional Requirements: Latency, Throughput, Availability and Scale

How to turn a vague prompt such as "design a photo app" into requirements you can design for: functional requirements, clarifying questions, and non-functional requirements stated as numbers, including latency percentiles, throughput, availability nines, durability and consistency.

On this page

Key takeaways

  • Functional requirements say what the system does; non-functional requirements say how well it must do it, and they drive most architecture decisions.
  • A non-functional requirement is only useful when it is measurable, for example "p99 read latency under 200 ms" rather than "fast".
  • Use percentiles, not averages, for latency, and remember that one slow call among many makes the whole request slow.
  • Availability multiplies across dependencies in series; redundancy helps only when failures are independent.
  • Availability, reliability and durability are different promises, and different features of one product can need different consistency.

"Design Instagram." Two words, and a candidate who starts drawing boxes immediately has already made a dozen decisions without noticing: that there are videos (or not), that there are stories (or not), that the system serves the whole world (or one country), that a photo must never be lost (true), that a like count must be exact at every instant (probably not). Every one of those silent decisions changes the design.

Requirements are where you make those decisions out loud. This article shows you how to ask the right questions, how to split requirements into functional and non-functional, and how to turn words like "fast" and "reliable" into numbers you can design against.

What you will learn

#
  • The difference between functional and non-functional requirements, with examples.
  • A reusable list of clarifying questions for any design prompt.
  • What scalability, latency, throughput, availability, reliability, durability and consistency mean, in plain words and as numbers.
  • Why percentiles matter more than averages, and how a single slow dependency hurts many requests.
  • How to calculate the availability of a chain of components, and what redundancy buys.
  • How requirements conflict, and how to state a trade-off.
  • How to spend the first five minutes of an interview.

Why requirements come first

#

Architecture is a set of answers. Requirements are the questions. If you skip the questions, you end up answering ones nobody asked.

Two systems that sound similar can need completely different designs:

College canteen ordering app

National food delivery platform

Users

About 2,000 students

Tens of millions

Peak

Lunch hour, one campus

Dinner hours, many cities at once

Hard part

Simple menu, payment, order queue

Matching orders to delivery partners in real time, surges, partner location updates

Reasonable design

One app server, one database, a payment provider

Many services, partitioned data, queues, real-time location pipeline

Both are "food ordering". Only the requirements tell you which one you are building.

Functional requirements: what the system does

#

A functional requirement describes a behaviour: something a user or another system can do, or something the system does on its own. They are usually verbs.

For our running example, the photo-sharing app Pixly from article 01:

  1. A user can upload a photo with a caption.
  2. A user can follow other users.
  3. A user can see a home feed of recent photos from people they follow.
  4. A user can like and comment on a photo.
  5. The system creates thumbnails for each uploaded photo.

Just as important is what is out of scope. In an interview you have 45 minutes, so you agree with the interviewer to leave things out:

  • Out of scope: video, stories, direct messages, search, ads, content moderation details.

Writing the out-of-scope list protects you. If the interviewer later asks about search, you can say "we left search out; shall I add it?" instead of looking unprepared.

Clarifying questions you can reuse

#

These questions work for almost any prompt. You will not ask all of them every time; pick the ones that change the design.

Topic

Questions

Users and scale

How many users in total? How many active per day? Is growth expected? Where are they (one country, worldwide)?

Core features

Which three or four features matter most? What is explicitly out of scope?

Read and write pattern

Is the system read-heavy or write-heavy? What is created, and how often is it read?

Data

How big is each item (a tweet, a photo, a video)? How long must we keep it? Can it be deleted?

Latency

What must feel instant? What can take seconds or minutes?

Consistency

Must every user see the latest data immediately, or is a short delay acceptable? Which data must never be wrong?

Availability

What happens to the business if this is down for an hour? Are some features more critical than others?

Security and privacy

Who can see what? Is there personal or payment data? Any regulations?

Integrations

Payment providers, email or SMS providers, maps, external APIs?

Constraints

Budget, team size, existing technology, deadlines?

Good questions have a reason you can state. "Is a short delay acceptable for like counts? Because if so, I can update them asynchronously and cache them aggressively" shows the interviewer why you are asking.

Non-functional requirements: how well the system does it

#

A non-functional requirement (also called a quality attribute) describes a property of the system as a whole: how fast, how available, how correct, how secure. These drive most architecture decisions. Two systems with the same features but different non-functional requirements look completely different.

The rule that matters most: a non-functional requirement must be measurable. "The feed should be fast" cannot be designed for or tested. "The feed loads in under 300 ms for 99% of requests" can.

Scalability

#

Scalability is the ability to handle more load by adding resources, without redesigning the system. Load can mean more users, more requests, more data or larger items.

  • Vertical scaling (scale up): a bigger machine with more CPU, memory or disk. Simple, but there is a ceiling, and it is still one machine.
  • Horizontal scaling (scale out): more machines sharing the work. Much higher ceiling, but the system must be designed so work can be split.

A useful way to think about it: in a scalable system, doubling the hardware roughly doubles the capacity. In a poorly scalable one, some shared component (often a single database) becomes the limit, and adding machines elsewhere does nothing.

Measurable form: "Handle 5,000 photo uploads per second at peak, and grow to 3 times that without redesign."

Latency and throughput

#

These two are often confused.

  • Latency is how long one request takes, from the moment it is sent to the moment the response arrives. Measured in milliseconds.
  • Throughput is how many requests the system completes per unit of time. Measured in requests per second (often written RPS or QPS, queries per second).

An analogy: a highway. Latency is how long it takes one car to drive from city A to city B. Throughput is how many cars arrive at city B per hour. Adding lanes increases throughput without making any single car faster. A higher speed limit lowers latency.

The two are linked by a simple and very useful relationship called Little's Law:

Code
requests in progress at once  =  throughput  x  average latency

If your service handles 2,000 requests per second and each takes 0.2 seconds, then on average 2,000 x 0.2 = 400 requests are in progress at any moment. If one server can handle 100 concurrent requests (for example, it has 100 worker threads), you need at least 4 servers, plus headroom. You will use this in article 07.

Notice what happens when latency rises. If a slow database makes each request take 1 second instead of 0.2, the same 2,000 RPS now means 2,000 requests in progress, five times more. Threads, connections and memory run out. Slowness turns into overload. That is why latency is not only a user-experience concern.

Why averages lie: percentiles

#

Suppose you measure 100 requests. Ninety-eight take about 20 ms and two take 3 seconds. The average is roughly (98 x 20 + 2 x 3,000) / 100 = 79.6 ms. That number describes nobody: almost everyone got 20 ms, and two people waited 3 seconds.

Percentiles describe the distribution instead:

  • p50 (median): half of requests are faster than this. The typical experience.
  • p95: 95% of requests are faster. Only 1 in 20 is slower.
  • p99: 99% are faster. The "tail" that 1 in 100 requests experiences.

Google's SRE book recommends percentiles over averages for exactly this reason: averages hide the slow tail that real users feel (Service Level Objectives).

Why should you care about 1 in 100? Because one page load is often many requests. If a page needs 100 backend calls and each has a 1% chance of being slow, the chance that at least one is slow is:

Code
1 - 0.99^100  =  1 - 0.366  =  about 63%

So a p99 problem in one service becomes a problem for most page loads. This is called tail latency amplification, and it is why mature systems set targets on p99, not on the average.

Measurable form: "Feed read: p50 under 100 ms, p99 under 300 ms, measured at the server."

Availability

#

Availability is the fraction of time (or of requests) for which the system works. It is usually written as a percentage with "nines".

Availability

Allowed downtime per year

Allowed downtime per day

99% ("two nines")

3.65 days

14.4 minutes

99.9% ("three nines")

8.76 hours

1.44 minutes

99.95%

4.38 hours

43.2 seconds

99.99% ("four nines")

52.6 minutes

8.64 seconds

99.999% ("five nines")

5.26 minutes

0.87 seconds

These figures come from the availability table in Google's SRE book (Availability Table). Each extra nine allows ten times less downtime and usually costs far more than ten times as much engineering, because it rules out manual fixes: nobody can wake up, log in and fix a problem in 8.64 seconds.

You can measure availability two ways:

  • Time-based: uptime divided by total time.
  • Request-based: successful requests divided by total requests. This is usually more meaningful for web services, because "up but failing 30% of requests" is not really up.

Availability in series.

When a request must pass through several components, and the request fails if any of them fails, their availabilities multiply:

Code
Load balancer 99.99%  x  App 99.9%  x  Database 99.95%  = 0.9999 x 0.999 x 0.9995  = about 0.9984, or 99.84%

The chain is less available than its weakest link. Every dependency you add to the critical path lowers the total. That is one reason to keep the synchronous path short and push non-essential work to the background (article 05).

Availability with redundancy.

When you run two copies of a component and the system works if either copy works, the probability that both fail at once is the product of their failure probabilities:

Code
One server:  99%  available, 1% unavailableTwo servers: unavailable only if both fail = 0.01 x 0.01 = 0.0001             available = 1 - 0.0001 = 99.99%

Reliability

#

Reliability is the system doing the right thing: returning correct results, not corrupting data, not charging twice. A system can be available but unreliable. A search page that responds instantly with wrong results is "up" but useless.

Measurable form: "No duplicate charges. Fewer than 0.1% of requests return a server error."

Durability

#

Durability is the promise that data, once acknowledged as saved, is not lost, even if machines, disks or a whole data centre fail. It is different from availability: a system can be temporarily unavailable (you cannot read your photo for ten minutes) while still being perfectly durable (the photo is safe and comes back).

Durability is achieved by keeping several copies in places that fail independently. For example, Amazon states that S3 Standard is "designed to provide 99.999999999% durability and 99.99% availability of objects over a given year", and stores objects across a minimum of three Availability Zones (Data protection in Amazon S3). Notice that the durability figure (eleven nines) is far higher than the availability figure (four nines). Losing data is much worse than being briefly unreachable, so durability is engineered to a much higher standard.

Measurable form: "A photo acknowledged as uploaded is never lost. Target: no data loss from any single-zone failure."

Consistency

#

Consistency, in system design, usually means: after data changes, do all readers see the change, and how soon? (The word means something different in ACID transactions; article 12 covers that meaning.)

  • Strong consistency: once a write succeeds, every later read sees it. Simple to reason about, harder to make fast and highly available across many machines.
  • Eventual consistency: after a write, different readers may see old data for a short time, but all copies converge if no new writes arrive. Easier to scale and keep available.

The key insight: different parts of one product need different consistency. For Pixly:

Data

Consistency needed

Why

A user's password change

Strong

An old password must stop working immediately

The photo a user just uploaded, shown to that user

Read-your-own-writes

The uploader must see their own photo, or they will upload it again

Like count shown to others

Eventual

Nobody is harmed if it shows 1,203 instead of 1,205 for a few seconds

Feed of followed users' photos

Eventual

A delay of seconds is acceptable

Article 19 makes these ideas precise. For now, learn to ask "which data must be exactly right, right now?" for every design.

Security and privacy

#

Who can read and change what? Is there personal data, payment data or health data? Must data stay in a particular country? Measurable forms include "all traffic encrypted in transit", "only the owner and followers can see a private account's photos", "access to payment data is logged". Article 28 covers the architecture.

Other qualities worth naming

#
  • Maintainability: can a team of five change this safely every week?
  • Cost: what is the budget? A design that needs 2,000 servers for a hobby project is wrong, however elegant.
  • Observability: can we tell what is happening inside the system (article 25)?
  • Operability: can it be deployed, scaled and recovered without heroics?

SLIs, SLOs and SLAs

#

Production teams formalise non-functional requirements with three related terms, defined in Google's SRE book (Service Level Objectives):

Term

Meaning

Example

SLI (service level indicator)

A measured quantity

Percentage of feed requests served in under 300 ms

SLO (service level objective)

A target for an SLI

99% of feed requests in under 300 ms, measured over 30 days

SLA (service level agreement)

A contract with consequences if the SLO is missed

Customers get a service credit if availability falls below 99.9% in a month

You do not need SLAs in an interview, but stating your non-functional requirements as SLO-style targets ("99.9% of uploads succeed, p99 under 2 seconds") is an easy way to sound precise. Article 25 returns to SLOs and alerting.

Turning vague words into numbers

#

Vague requirement

Measurable version

"It should be fast"

"p99 latency under 200 ms for reads, under 1 s for uploads"

"It should handle lots of users"

"10 million daily active users, 3,000 reads per second average, 10,000 at peak"

"It should always be up"

"99.95% of requests succeed each month; uploads may degrade, viewing must not"

"Don't lose data"

"Acknowledged writes survive the loss of any one data centre"

"Show the latest data"

"Users see their own changes immediately; others within 5 seconds"

"It should be secure"

"TLS everywhere; only owners can delete photos; every admin action is logged"

You will learn to produce the traffic numbers in articles 06 and 07.

Requirements conflict: stating the trade-off

#

Non-functional requirements pull against each other. Recognising the tension and saying which side you chose is a large part of what interviewers grade.

Tension

Example

Consistency vs latency and availability

Keeping every replica exactly up to date before replying makes writes slower, and may force you to refuse writes during a network failure

Durability vs write latency

Waiting for a copy in a second data centre before acknowledging a write adds the network round trip to every write

Availability vs cost

Running a full second copy of everything in another region roughly doubles infrastructure spend

Freshness vs load

Caching reduces database load but means users may see slightly old data

Security vs convenience

Shorter session lifetimes are safer but make users log in more often

A good way to state a trade-off has three parts: what you chose, what it costs, and why the cost is acceptable here.

"I'll update like counts asynchronously and cache them for a few seconds. The cost is that counts can lag by a few seconds. That's acceptable because likes are not financial data, and it removes most of the write load from the hot path."

Worked example 1: Pixly's requirements

#

Here is what a complete requirements section looks like for Pixly. In an interview this would be spoken and written as short notes, in about five minutes.

Functional (in scope)

  1. Upload a photo (up to 10 MB) with a caption.
  2. Follow and unfollow users.
  3. View a home feed of photos from followed users, newest first.
  4. Like a photo; see like counts.

Out of scope: video, comments, search, direct messages, moderation, ads.

Scale (assumptions, to be estimated in article 06): 50 million registered users, 10 million daily active, mostly in one region.

Non-functional

Quality

Target

Feed latency

p99 under 300 ms

Upload latency

p99 under 2 s to acknowledge (thumbnails can follow later)

Availability

99.95% for viewing; uploads may degrade during incidents

Durability

An acknowledged photo is never lost, even if one data centre fails

Consistency

Uploader sees own photo immediately; followers within 10 seconds; like counts eventually consistent

Security

Private accounts visible only to approved followers; all traffic over TLS

Notice how much design this already implies. "Thumbnails can follow later" suggests a queue and workers. "Never lost, even if one data centre fails" suggests object storage that keeps copies in several zones. "Followers within 10 seconds" means the feed does not need to be strongly consistent, which opens the door to precomputing feeds. You have not drawn a single box, and the shape of the design is already visible.

Worked example 2: the same method, a very different system

#

A company asks you to design an internal tool where 300 HR staff run monthly payroll for 20,000 employees.

Functional: upload salary changes, run the payroll calculation, approve, export bank payment files, view history.

Non-functional:

Quality

Target

Why it differs from Pixly

Scale

300 users; one big batch job per month

Tiny traffic; no need for caches or sharding

Correctness

Every calculation must be exact and reproducible

Errors are financial and legal

Consistency

Strong; no reader may see half-applied changes

Transactions in one relational database

Security

Strict role-based access; every change audited

Salary data is highly sensitive

Availability

Business hours only; a few hours of downtime outside payroll week is acceptable

Lowering the target saves cost and complexity

Durability and history

Keep records for years; restore to any point in time

Audits and disputes

The right design here is modest: a well-run relational database with backups and point-in-time recovery, a single application with strong authorisation and audit logging, and a background job for the payroll run. Pixly's design would be wrong for this, and this design would be wrong for Pixly. Same method, different requirements, different architecture.

Common mistakes

#
  • Designing before asking. The interviewer expects questions. Silence followed by a diagram is a red flag.
  • Unmeasurable targets. "Highly available" means nothing until it has a number.
  • Asking for five nines by default. Each nine costs a lot. Ask what the business actually needs.
  • One consistency level for everything. Choose per feature.
  • Using averages for latency. Talk about p95 or p99.
  • Forgetting durability. Being briefly down is recoverable; losing data often is not.
  • Too many features. Three to five core features, clearly agreed, beat ten vague ones.
  • Not writing down the out-of-scope list. It saves you later in the interview.

In an interview: the first five minutes

#
  1. Restate the problem in one sentence.
  2. Ask five to eight clarifying questions, each with a reason.
  3. Write three to five functional requirements and an out-of-scope list.
  4. Write the non-functional requirements as numbers, and mark the one or two that will drive the design (for example "read-heavy, p99 under 300 ms" or "no double booking").
  5. Confirm with the interviewer: "Does this match what you have in mind?"

Then move to estimation. Article 29 turns this into a timed checklist.

Exercises

#

Exercise 1

Functional or non-functional?

#

Classify each requirement, and rewrite any vague non-functional one as a measurable target.

  1. Users can reset their password by email.
  2. The system should be very fast.
  3. Search results appear within 500 ms for 99% of queries.
  4. Admins can export a monthly report as CSV.
  5. The app should never go down.
  6. Uploaded documents must not be lost even if a data centre fails.

Exercise 2: Availability arithmetic

#

A request passes through a load balancer (99.99%), an application tier (99.9%) and a database (99.95%), all required.

  1. What is the combined availability, and roughly how many hours of downtime per year does that allow?
  2. You run the application tier as two independent copies, either of which can serve the request. What is the new combined availability?
  3. Why might the real improvement be smaller than your calculation?

Exercise 3: Percentiles

#

Twenty requests took these times in milliseconds:

Code
12, 15, 14, 13, 16, 18, 15, 14, 13, 17, 19, 15, 14, 16, 900, 15, 13, 14, 16, 1200

Compute the average, p50, p90 and p95 (use the nearest-rank method: sort the values, and the pth percentile is the value at position ceiling(p/100 x n)). Which numbers would you put in a performance report, and why?

Exercise 4: Write the requirements

#

Write the requirements section for "Design an online ordering system for a college canteen". Include at least five clarifying questions with the reason for each, functional requirements, an out-of-scope list and measurable non-functional requirements.

Show solutionHide solution
  1. Functional. It is a behaviour the user can trigger.
  2. Non-functional, vague. Measurable: "p99 page load under 500 ms; p99 API latency under 200 ms."
  3. Non-functional, already measurable.
  4. Functional.
  5. Non-functional, vague and unrealistic. "Never" is not achievable. Measurable: "99.9% of requests succeed each month (about 43 minutes of failures allowed)." Then ask which features matter most during an outage.
  6. Non-functional (durability), measurable enough. It names the failure the system must survive. You could add "acknowledged uploads only", which makes clear when the promise starts.

Exercise 2

Show solutionHide solution
  1. 0.9999 x 0.999 x 0.9995 = 0.99840065, about 99.84%. Unavailability is about 0.16% of a year: 0.0016 x 8,760 hours = about 14 hours per year.
  2. Two independent application copies are unavailable together with probability 0.001 x 0.001 = 0.000001, so the tier becomes 99.9999% available. Combined: 0.9999 x 0.999999 x 0.9995 = about 99.94%, or roughly 5.3 hours of downtime a year. The database (99.95%) is now the weakest link, so further gains must come from there.
  3. The calculation assumes the two copies fail independently. In practice they often share causes of failure: the same deployment (a bad release breaks both), the same network, the same zone, the same database connection limit. The real gain is smaller unless you remove those shared causes, for example by deploying to different zones and rolling out releases gradually.

Exercise 3

Show solutionHide solution

Sorted: 12, 13, 13, 13, 14, 14, 14, 14, 15, 15, 15, 15, 16, 16, 16, 17, 18, 19, 900, 1200.

  • Sum: 12 + (13 x 3) + (14 x 4) + (15 x 4) + (16 x 3) + 17 + 18 + 19 + 900 + 1,200 = 2,369. Average = 2,369 / 20 = 118.45 ms.
  • p50: position ceiling(0.50 x 20) = 10, value 15 ms.
  • p90: position 18, value 19 ms.
  • p95: position 19, value 900 ms.

The average (118 ms) describes no real request: 18 of 20 took under 20 ms and two took around a second. Report p50 (typical experience, 15 ms) and p95 or p99 (the tail, 900 ms or more). The tail tells you there is a real problem worth investigating, such as a slow query, a garbage-collection pause or a cold cache, which the average hides.

With only 20 samples, p95 and p99 are not statistically reliable. In practice you would compute percentiles over thousands of requests.

Exercise 4

Show solutionHide solution

Clarifying questions (with reasons)

  1. How many students and staff, and how many orders at the lunch peak? Decides whether one server is enough.
  2. Is payment online, at the counter, or both? Online payment adds a provider integration and idempotency concerns.
  3. Does the menu change daily, and do items run out? Stock tracking needs consistent counts.
  4. Should students be told when their order is ready? Needs a notification channel: in-app, push or SMS.
  5. One canteen or several? Several counters means routing orders to the right kitchen.
  6. Is there an existing student login? Reuse it instead of building accounts.

Functional: browse today's menu; place an order; pay online; kitchen sees a queue of orders; student is notified when the order is ready; order history.

Out of scope: delivery, loyalty points, nutritional analysis, multiple campuses.

Non-functional (assuming 3,000 users, 1,500 orders between 12:30 and 13:30):

Quality

Target

Throughput

1,500 orders in an hour is under 1 order per second on average; design for 10 per second at the rush

Latency

Menu loads p99 under 1 s; order confirmation under 2 s

Availability

99.9% during canteen hours; maintenance allowed at night

Correctness

No order charged twice; no item sold when out of stock

Security

Students see only their own orders; kitchen staff see the queue

Design implication: a single application with a relational database, a payment provider with idempotent requests, and a simple notification mechanism is enough. The hard parts are correctness (stock and payment), not scale.

Where to go next

#
  • Next: How a Web Request Travels: DNS, TCP, TLS and HTTP for System Design follows one request through the network, so you can see where latency comes from.
  • Numbers: articles 06 and 07 turn "10 million daily users" into requests per second, storage and bandwidth.
  • Going deeper: availability and redundancy return in article 24, consistency in article 19, and SLOs in article 25.

Sources & further reading

  1. sre.google
  2. sre.google
  3. docs.aws.amazon.com
  • Guide · Technology

    Start Here: Your Roadmap from Zero to Job-Ready DSA

  • Guide · Technology

    Heaps and Priority Queues

  • Guide · Career

    A LinkedIn Profile That Gets Recruiter Messages