River
Y CombinatorBacked by Y Combinator
FREE TEMPLATE

Non-Functional Requirements Spec Template

A requirement with no percentile gets graded at whatever percentile whoever runs the test happens to pick, and that is almost always the median.

Free download  ·  No account needed

Non-functional requirements get waved through at launch for one reason, and it is not that nobody cares about performance. It is that nobody can grade them. This pack gives every requirement four columns: what is measured, where it is measured, over what window, and at what percentile. Then it measures where the product actually sits, before any threshold is negotiated. In the worked example that took two days against telemetry already being collected.

The percentile decides the verdict more often than the threshold does. The Google SRE book puts it plainly in the chapter on service level objectives: monitoring based only on average latency shows no change over a day when the tail has moved, while a high-order percentile shows a plausible worst case. Core Web Vitals thresholds are assessed at the 75th percentile of page views for the same reason, which is why a target graded at the median is a different measurement wearing the same name.

Of 23 drafted requirements, 6 were testable as written, 8 had a metric and no percentile, 5 had no metric at all, and 4 were not requirements. Of the 14 that could be measured, 5 were already met and 4 passed at p50 and failed at their own percentile. Sits next to the feasibility brief, the stories the release is built from and the internal tooling the same launch needs. It is not a service level agreement, which is a commercial promise with a credit attached.

Twenty-three requirements, fourteen that can be graded, seven that are work

The register with all four columns filled, the baseline measured before any target was negotiated, and what the drafted list actually cost.

Requirement Register

Illustrative, for a fictional wholesale order-management product called Ellerby. 23 requirements collected from the draft list, two signed contracts, a security questionnaire and the last three incident reviews.

As draftedVerdictRewritten with all four columnsWindow and percentile
N-04 Order search returns quicklyNeeds a percentilep95 of order search latency at or under 800 ms, timed at the edgep95, weekdays 09:00 to 17:00, rolling 28 days
N-06 The order list renders without a visible delayNeeds a percentileLargest Contentful Paint at or under 2,500 ms, field data from real sessionsp75 of page views, rolling 28 days
N-02 99.9 percent availabilityTestable as writtenSuccessful over total requests at the edge, timeouts counted as failuresCalendar month, no percentile, it is a ratio
N-13 All traffic uses TLS 1.2 or aboveTestable as writtenNo endpoint negotiates below TLS 1.2, checked by scanEvery deploy, binary per endpoint
N-19 No customer data leaves the EU regionNo metric existsZero egress to a non-EU destination. Needs destination logging firstWould be continuous, binary per event
N-01 The application should feel fast to useNot a requirementNo observable. Split into N-04 and N-06 and deletedn/a
N-22 Search results are ranked before the page paintsNot a requirementA functional requirement in performance language. Moved to the specn/a
23 drafted6 testable, 8 need a column, 5 unmeasurable, 4 removed19 requirements survive, 14 measurable today9 carry a percentile, 5 are binary

Four columns decide whether a sentence is a requirement at all: what is measured, where, over what window, and at what percentile. Only 6 of 23 arrived with all four, and the one that was drafted properly came from an engineer rather than from a checklist. Five rows are binary and correctly carry no percentile, because inventing one for a TLS floor is a different error in the same family. Two of the four removed rows were functional requirements wearing performance language, and they moved into the spec rather than being deleted.

Current State Baseline

Measured before any threshold was negotiated. Two days of one engineer against telemetry Ellerby was already collecting.

RequirementTargetp50p90p95p99Result
N-04 Order search latencyp95 <= 800 ms340 ms760 ms2,140 ms6,900 msFails at p95, passes at p50
N-06 Order list paintp75 <= 2,500 ms1,240 ms4,980 ms4,980 ms9,100 msFails at p75 (3,410 ms)
N-09 Webhook deliveryp95 <= 30 s1.9 s12 s214 s1,840 sFails at p95, passes at p50
N-12 Report exportp95 <= 20 s6.2 s19 s74 s310 sFails at p95, passes at p50
N-08 Public API latencyp99 <= 500 ms48 ms96 ms210 ms380 msAlready met, 120 ms spare
N-20 Rollback durationp90 <= 10 min4 m 10 s9 m 30 s9 m 30 s11 m 40 sMet by 1 m 20 s at p90
N-02 Availability>= 99.9% monthlyn/an/an/an/aFails, 99.62 percent
N-16 Audit log retention>= 365 daysn/an/an/an/aFails, 30 days
14 rows baselined9 percentile, 5 binary2 days of one engineer5 met, 4 tail-only, 3 fail, 2 need load

N-04 is the row the register exists for. Reported as an average it passes with 460 ms of headroom. 71 percent of searches land at or under 800 ms, so 11,948 of 41,200 daily searches do not, and a user running six searches sees all six under target on about 13 percent of days. The median passes and roughly 87 percent of active users hit at least one search slower than the requirement every day. Four of the 12 gradeable rows behave this way, which is a third of them silently passing under an average. Note N-20 as well: met at p90 by 1 minute 20 seconds, which is thin enough to alert on rather than tick.

What 23 drafted rows actually cost

The launch estimate before the register treated the drafted list as 23 items of work. After the baseline it is 7 items, 5 regression guards, 2 load tests and 4 deletions.

OutcomeRowsEngineer-weeksWhat happens to them
Fails at its own percentile, passes at p5047.5Real work. N-04 at 3.0, N-12 at 2.0, N-06 at 1.5, N-09 at 1.0
Fails at every percentile34.5Real work, and the three that would have blocked the launch
Already met50.0Regression guards with an owner and a recurring check, not scope
Cannot be baselined2unknownLoad harness first. One asks for 7x the observed peak
No metric exists53.5 to instrument2 recommended at 2.5 ew, 3 deferred with a reason
Not a requirement40.02 moved into the spec, 2 deleted
Total2312.0 of real workPlus a 2.5 ew instrumentation decision made in the open

Five already-met rows sat on a 23-item list looking identical to the seven that were real, which is how a launch estimate inflates by a third without anybody lying. The timing argument is sharper still. The three outright failures are worth 4.5 engineer-weeks. Found at a week-11 readiness review in a twelve-week cycle, that is one week and three engineers, so 3 weeks of capacity against 4.5 weeks of work. Found in week 2 from the baseline, the same work spread over nine weeks is about a sixth of one engineer. The two days the baseline cost buys nine weeks of room.

What is in the pack

01

Four columns that decide whether a sentence is a requirement

What is measured, where it is measured, over what window, and at what percentile. A row that cannot fill all four is not a requirement yet.

02

A percentile column, and binary rows that correctly have none

Nine rows carry a percentile and five are binary, because inventing one for a TLS floor is a different error in the same family.

03

Current State Baseline, measured before any target is set

p50, p90, p95 and p99 on every row that has a distribution, so the shape of the failure is visible rather than a single number.

04

The already-met rows, separated out

A third of the measurable set in the worked example. They stop being launch scope and become regression guards with an owner and a recurring check.

05

Instrumentation Gap List with a price on each row

For requirements nothing measures, the cost of building the measurement and an explicit decision to build it, defer it or drop the row.

06

An acceptance approach written before the pressure

How each row gets demonstrated, who signs it, and what happens when it is missed, decided while nobody is a week from launch.

How it works

  1. 1

    Send everything

    The draft list, plus the contracts, the security questionnaire and the last few incident reviews.

  2. 2

    Fill four columns

    Metric, measurement point, window, percentile. Rows that cannot fill them get sorted rather than deleted.

  3. 3

    Measure before negotiating

    Baseline every gradeable row from telemetry you already collect, and record the whole distribution.

  4. 4

    Read the split

    Already met, failing on the tail, failing outright, or needing instrumentation nobody has built yet.

Frequently asked questions

What do I need before this is useful?

The draft requirements, plus the places the hard commitments actually live: signed contracts, completed security questionnaires, the public trust page and the last few incident reviews. Then whatever the product already measures. Half the exercise is finding out which rows can be baselined today from data you are already collecting.

Why does the percentile matter this much?

Because it decides the verdict. In the worked example, order search is targeted at 800 ms and measures 340 ms at p50 and 2,140 ms at p95. Same week, same data, opposite answers. Reported as an average it passes with 460 ms to spare while 11,948 of 41,200 daily searches miss the target.

Is an already-met requirement a wasted row?

No, it is the second most useful outcome after a failure. It stops being launch scope, which matters when five of them are sitting on a list of 23 looking like work. It becomes a regression guard with an owner and a check, which is what keeps it true three releases later.

What about requirements nothing measures?

They get priced rather than deleted. The two honest options are to build the measurement or to drop the row, and the pack costs each one so the choice is made in the open. The worst case is a property asserted in a contract and unverifiable internally, because no version of that answer is defensible.

Is this the same as writing SLOs?

Related and not the same. An SLO is an operating artifact for a system already live, with an error budget attached, and a service level agreement is a commercial promise with a credit behind it. This is the requirement stage that comes before either, and the measurement methods here are what those two later inherit.

When should this happen in the cycle?

Early enough to act on. The three outright failures in the worked example are worth 4.5 engineer-weeks. Found at a week-11 readiness review, that is three engineer-weeks of remaining capacity against 4.5 weeks of work. Found in week 2, it is a sixth of one engineer. The same finding, priced differently.

What if a requirement is missed at the readiness review?

That is decided per row when the register is written, not on the day. Blocks the release, ships with a dated remediation, or ships with the threshold formally relaxed. The last one means the number was wrong and gets a new rationale, which is a different record from a commitment to fix it.

Find out how many of your requirements can be graded

Send the draft list and whatever the product already measures. What comes back first is the split: testable, missing a column, unmeasurable, or not a requirement at all.

Make my requirements testable