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.
What is in the pack
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.
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.
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.
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.
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.
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
Send everything
The draft list, plus the contracts, the security questionnaire and the last few incident reviews.
- 2
Fill four columns
Metric, measurement point, window, percentile. Rows that cannot fill them get sorted rather than deleted.
- 3
Measure before negotiating
Baseline every gradeable row from telemetry you already collect, and record the whole distribution.
- 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