Skip to content
beginner Phase 1 · The Architect Role and Trade-off Thinking

Quality Attributes and NFRs

Capture performance, scalability, reliability, and security as testable requirements.

50m
0 problems
Topic Progress 0%

Why 'The System Must Be Fast and Scalable' Ends Every Design Meeting

A product manager writes the performance requirement for the new checkout service: 'The system shall be fast, highly available, and scalable.' The team implements something, ships it, and the first real argument happens in a incident channel at 2 a.m. — because 'fast' meant 200 ms to the frontend team, 50 ms to the mobile team, and 'fast enough that nobody complains' to the DBAs, and none of those were written down.

Quality attributes describe how a system behaves under conditions rather than what it does. Functional requirements say the service computes a discount; quality attributes say what happens to that discount calculation when 5,000 shoppers hit it during a flash sale, when the primary database region is unreachable, or when an attacker replays last year's tokens. The classic split calls these non-functional requirements (NFRs), but the more useful term is quality attributes because 'non-functional' tricks people into thinking they are optional polish rather than the properties users actually pay for.

The cure for vagueness is the scenario format from the SEI's attribute work. Every quality attribute scenario names six things:

Part Question Example: latency
Source Who or what causes it? A logged-in shopper
Stimulus What happens? Adds an item to the cart
Environment Normal, peak, or degraded? Peak: 3× normal traffic
Artifact What is affected? The cart API, not the whole system
Response What does the system do? Persists the item and returns the new total
Response measure How do we know it worked? p99 < 200 ms, error rate < 0.1%

The response measure is the load-bearing part. Without it, you have a story, not a requirement. Compare the two versions a reviewer sees:

Weak:  'Checkout must be fast and handle load.'
Good:  'During peak (3x median traffic, 5k concurrent sessions), the
       cart API completes 95% of add-to-cart calls in < 100 ms and
       99% in < 250 ms at the edge, with error rate < 0.1%, using
       read replicas; no request may be lost on replica failover.'

The good version can be turned into a load test, an SLO, and a capacity plan. The weak version can only be argued about.

Five attributes cover most of what you will be asked to specify, and each has a canonical measure worth memorizing because they come up in interviews constantly:

Attribute The question it answers Typical measure
Latency / throughput How fast, at what load? p99 ms at N req/s
Availability How much of the time does it work? 99.95% monthly, excluding planned work
Reliability / durability Does anything get lost or corrupted? RPO seconds, bit rot rate
Scalability What happens as load grows? Cost and latency curves at 2x, 5x, 10x
Security Who can do what, and how fast do we detect it? mTLS coverage, time-to-revoke

A discipline that separates juniors from seniors here: when someone hands you an NFR you cannot measure, the reply is a single question — 'what test would prove that to you?' If they cannot answer, the requirement does not exist yet, and writing it into the design is premature. Capture it as an open question, which is exactly the subject of Constraints, Assumptions, and Risks.

Ranking Attributes Before Optimizing Everything at Once

A design review where every quality attribute is 'critical' produces two failure modes. Teams optimize the attribute that is easiest to demonstrate — usually latency, because a benchmark graph looks impressive — while the attribute that actually governs revenue, often consistency of inventory counts, goes unspecified. Or they spread effort thin, bolting on a caching layer 'for performance' and a second region 'for availability', each half-finished. Ranking attributes with stakeholders prevents unbounded optimization of everything at once, and the ranking is a designed conversation, not a survey.

Start by eliciting each attribute independently, because stakeholders anchor each other if you put them in one room. Send five to ten scenarios and ask each stakeholder to mark each one must-have, should-have, could-have, or won't-have this quarter (MoSCoW), then bring the answers to a two-hour session. Expect the disagreements — that is the point of the session:

Stakeholder Wants ranked high Why
Product Availability 99.95%, fast mobile p75 Churn correlation with failed checkouts
Finance Exactly-once ledger writes Audit and reconciliation cost
Support Fast recovery (RTO < 30 min) Ticket volume correlates with outage length
Platform Predictable cost at 5x Cloud spend reviews

From there, build a small utility tree: each attribute, its scenario, a rough business weight (1–5), and a technical difficulty score (1–5). Weight divided by difficulty is crude, but it does its job — it makes visible that a must-have attribute with difficulty 5 is a project, while a could-have with difficulty 2 is a ticket. The output is a short list: typically two must attributes the architecture must be designed around, two to three that must be supported, and the rest explicitly deferred. Deferral is a deliverable: writing 'durability below 99.999% is acceptable for recommendation logs, not for orders' prevents the team from rediscovering the question every sprint.

Watch for three ranking traps in the session:

  • Everything is a 5. Force ordering: 'if you could have only one of latency or availability this quarter, which one?' Pairwise comparison breaks ties that MoSCoW creates.
  • The loudest stakeholder wins. Capture the reasoning in writing so the ranking survives their absence, and re-rank quarterly when the business changes.
  • Attributes get ranked, scenarios do not. 'Availability' at 99.9% vs 99.99% is 43 minutes vs 4 minutes of downtime per month. The unit of ranking must be the full scenario with its measure, not the label.

Interviewers probe exactly this: 'how do you decide what to optimize first?' The strong answer describes eliciting scenarios independently, resolving disagreements by attaching each scenario to a business outcome, and producing an explicit deferral list. Hand-waving about 'balancing trade-offs' scores nothing. The deliverable of the session fits on one page: ranked scenarios, each with its measure, its owner, and a one-line business reason for its position, followed by the deferral list. That page comes back at every later design review, because the inevitable question - should we also add a cache for performance? - is answered by pointing at the ranking: caching serves the number-two attribute, while the number-one attribute, inventory consistency, would be harmed by a stale cache. The ranking does not end arguments about taste; it removes them from the agenda by pre-committing to what the business chose.

From Ranked Scenario to SLO, Load Test, and Alert

A ranked scenario with a response measure is still a document. It becomes architecture when three artifacts exist: an SLO the on-call can be held to, a test that reproduces the scenario, and an alert that fires when reality diverges from the measure. Walk the path with one attribute — peak-load latency — then compress the same recipe for the others.

Latency. Scenario: 5k concurrent sessions, cart API p99 < 250 ms at the edge. The SLO is written against what you can measure continuously, so edge latency (what the user sees) becomes the SLO, while server-side latency becomes the debugging dimension:

# slo.yaml — cart service
indicator:
  good:    p99(edge_latency_ms) < 250
  acceptable: p99(edge_latency_ms) < 400
window: 30d rolling
target: 99% of requests good
budget_burn_alert: > 2x expected burn rate over 1h

The load test is derived mechanically from the scenario: 5k sessions, a realistic mix (60% browse, 30% cart, 10% checkout), a ramp that holds peak for 30 minutes — long enough for caches, connection pools, and autoscalers to reach steady state. A 2-minute spike test that never lets pools warm is not this scenario. Then find the ceiling and write it down: 'the cart tier degrades past 8k sessions per node; adding a node is the documented scale step.' Capacity without a documented breaking point is another unmeasured NFR.

Availability. 99.95% monthly is 21.9 minutes of allowed downtime, so the SLO math forces the real discussion: what counts as down (5xx at the edge? health-check failure? partial degradation where checkout works but recommendations do not?), and what error budget buys. A team burning 60% of its budget in the first week should be freezing feature launches, and saying that in advance is the only way the policy holds under pressure.

Consistency and recovery. Finance's 'exactly-once ledger writes' becomes RPO: how much data can vanish in a failure? RPO 5 seconds means synchronous replication or a write-ahead shipping scheme; RPO 24 hours would allow nightly backups — an enormous architectural difference hiding behind one adjective. RTO (time to restore) similarly forces topology: 30-minute RTO may justify a warm standby; 4-hour RTO does not. Disaster recovery drills are the response measure — an untested failover plan is an assumption, and the risk register is where assumptions go to be tracked.

Security. The same format applies: stimulus is an attacker or a leaver, response is detection or prevention, and the measure is concrete — 'revoking an employee's credentials takes effect on every service within 60 seconds', 'all internal RPC requires mTLS, no exceptions', 'we detect credential stuffing within 5 minutes via anomaly rate alerts'. Vague security NFRs are the most common kind, and the scenario format is the most effective cure.

The final check before design work starts: every must-have scenario from the ranking session maps to exactly one test and one alert. Any scenario with no test is not committed to; any alert with no scenario is noise waiting to happen. Three habits keep the SLO honest once it is live. First, measure at the boundary the user experiences - edge latency, not server time - and keep server-side metrics as drill-down dimensions, because an SLO on internal numbers can read green while customers see errors. Second, set the alert on budget burn rate rather than on raw thresholds: a service missing its p99 target during a 10x spike for ten minutes is not a paging event, but burning a week of error budget in an hour is. Third, run the failover and revocation drills on a schedule, because the response measure of recovery and security scenarios is the only thing that proves the paper design survives contact with reality.

Quiz

1. Which requirement is a properly formed quality attribute scenario?

Question 1 options

2. In a ranking workshop, every stakeholder marks latency, availability, security, and cost as must-have. What is the best next move?

Question 2 options

3. A team states 99.9% monthly availability for its checkout service. How much allowed downtime does that permit, and what is the common follow-up question?

Question 3 options

4. Finance requires that no ledger write is ever lost during a database failover. Which quality attribute scenario does this most directly constrain?

Question 4 options

Flashcards

Question

What are the six parts of a quality attribute scenario, and which one is load-bearing?

Answer

Source, stimulus, environment, artifact, response, and response measure. The response measure is load-bearing: without a number ('p99 < 250 ms, error < 0.1%'), the scenario is a story that cannot become a load test, an SLO, or an alert.

Question

How do quality attributes differ from functional requirements?

Answer

Functional requirements say what the system does (computes a discount); quality attributes say how it behaves under conditions (at 5k concurrent users, during failover, against an attacker). The attributes are what users pay for — 'non-functional' is a misleading label that suggests optionality.

Question

Why elicit quality attribute scenarios from stakeholders independently before the ranking session?

Answer

Stakeholders anchor each other in a group, converging on whatever the loudest person says. Independent elicitation (MoSCoW per scenario), followed by a session that surfaces the disagreements, makes the conflicts — e.g., product wants availability while finance wants exactly-once writes — the explicit agenda instead of an unvoiced undertow.

Question

What does a utility tree do in quality attribute ranking?

Answer

It records each attribute scenario with a business weight and a technical difficulty score (1–5 each). The pairing exposes which scenarios must be designed around (high weight, high difficulty) versus which are single tickets, and it keeps the ranking about scenarios with measures rather than labels.

Question

What three artifacts turn a quality attribute scenario into an enforceable commitment?

Answer

An SLO with an error budget (e.g., 99% of requests under 250 ms over a 30-day window), a test that reproduces the scenario (long-hold load test, failover drill, credential-revocation rehearsal), and an alert that detects divergence (budget burn rate). Any must-have scenario lacking a test is not committed to.

Revision Notes

Key Takeaways

  • 1. Quality attributes describe behavior under conditions, not function; the response measure ('p99 < 250 ms at 5k sessions') is what makes them real requirements
  • 2. Elicit scenarios independently, rank them against business outcomes, and write down deferrals — optimizing everything thinly is the failure mode ranking prevents
  • 3. Rank full scenarios with measures, not labels: 99.9% vs 99.99% availability is 43 minutes vs 4 minutes of downtime per month
  • 4. Each committed attribute needs an SLO with an error budget, a test that reproduces the scenario, and a divergence alert
  • 5. RPO and RTO are quality attribute scenarios hiding behind adjectives like 'durable' and 'recoverable', and they decide topology (warm standby, synchronous replication) on their own

Interview Tips

  • • 'Write a performance requirement for checkout' — produce the full scenario: 3x peak traffic, named artifact, p99 measure at the edge, error rate; then say you'd convert it to an SLO with a 30-day window
  • • 'How do you decide what to optimize first?' — describe independent elicitation, utility-tree weighting of business value against difficulty, pairwise tie-breaking, and the explicit deferral list
  • • 'What is an error budget and what does it govern?' — the gap between SLO and 100%; it funds reliability work and gates feature launches when burn rate spikes
  • • 'Availability is 99.9% — what do you ask next?' — what counts as down (measurement boundary), whether maintenance is excluded, and how failover affects the numerator; shows you can enforce the number

Cheat Sheet

Quality Attributes and NFRs

Scenario anatomy: source → stimulus → environment → artifact → response → response measure. No measure = no requirement.

Attribute Scenario skeleton Measure
Latency N concurrent sessions, peak mix, 30-min hold p99 at edge + error rate
Availability Degradation / region loss 99.95% monthly = 21.9 min budget
Durability/recovery Component failure, region loss RPO (data destroyed), RTO (time to restore)
Scalability 2x, 5x, 10x load cost + latency curves, documented breaking point
Security Leaver, attacker, replay time-to-revoke, mTLS coverage, detection time

Ranking recipe:

  1. Elicit scenarios independently (avoid anchoring) — MoSCoW per scenario
  2. Build utility tree: business weight × technical difficulty
  3. Force pairwise ties ('only one this quarter') — loudness is not priority
  4. Produce an explicit deferral list; re-rank quarterly

SLO skeleton:

indicator: p99(edge_latency_ms) < 250   # good
          p99(edge_latency_ms) < 400   # acceptable
window: 30d rolling
target: 99% good
alert: budget burn > 2x expected over 1h

Definition of done: every must-have scenario maps to one test and one alert; every alert traces to a scenario.

Continue Learning