MG12 design
← All articles Essay · Requirements & delivery

The requirements nobody writes down

A good set of requirements now turns into a working system in days. That makes the half of the requirements almost nobody writes down, how it should behave rather than what it should do, the thing that decides whether you have built something you can actually run. Usability, accessibility, performance and scale are architectural, and none of them can be added afterwards at a sensible price.

Something genuinely changed in the last couple of years. A well-written set of requirements now becomes a working, deployed system in days rather than quarters. Not a prototype: a thing with a database, an interface, authentication and a URL.

Which means the requirements are no longer one input among many. They are very close to the whole specification of what you will end up with, because everything downstream that used to reinterpret them, argue with them and quietly fix them has been compressed into a process that takes them at their word.

An agent builds what you asked for, precisely. It will not tell you that the table cannot be operated by keyboard, or that the page issues forty queries, because you did not ask for it not to.

Everybody writes the same half

Functional requirements are what the system should do. Record the order. Send the confirmation. Let an agent reassign a case. They are concrete, they are easy to agree, and they are the natural thing to say when someone asks what you want.

Non-functional requirements are how it should behave while doing it. How fast, for how many people at once, how usable, how accessible, how it fails, what it costs to run. They rarely get written down, and the reason is a symmetric trap. Non-technical stakeholders describe outcomes and reasonably assume the rest is included, the way you assume a building will have fire exits. Technical people assume the non-functional side is engineering's business and will be handled later by someone with the right job title. Both are being sensible, and between them nobody says it out loud, so it never reaches the brief.

That gap has always existed. What has changed is that the slowness of building used to hide it. A system that took nine months gave you nine months of design reviews, accessibility audits and load tests happening alongside, catching things nobody had specified. Build the same system in a fortnight and those gaps are gone. Nothing filled them; they simply closed.

The four to name explicitly

Usability

Shneiderman's eight golden rules are still the most useful short checklist in the field: strive for consistency, seek universal usability, offer informative feedback, design dialogs to yield closure, prevent errors, permit easy reversal of actions, keep users in control, reduce short-term memory load.

Read them again as an engineer and notice something. At least half are not interface advice at all. Permit easy reversal of actions is a data model requirement: you cannot bolt undo onto a system that overwrites in place. Design dialogs to yield closure requires the journey to have persisted state, so a customer can leave and come back to something that remembers them. Offer informative feedback, for anything that takes real time, requires streaming or progress infrastructure that has to exist end to end. And strive for consistency is a property of the whole system that no individual screen can hold; it is the one thing you cannot add later at all, only rebuild toward.

Accessibility

WCAG 2.2, level AA, is the target worth naming in the requirement, because "make it accessible" is not a requirement, it is a hope. Naming the standard also gets you the things teams reliably miss: focus that is visible and never obscured, targets big enough to hit, no journey that depends on dragging, consistent help, and authentication that does not demand a cognitive test.

It is also no longer only good practice. For consumer-facing digital services in the EU, the Accessibility Act has applied since June 2025, and the UK public sector has had its own duty for years. But the practical argument is stronger than the legal one: an inaccessible component library infects every screen built from it. Retrofitting accessibility is not a pass over the UI, it is rewriting the components and then re-testing every page that used them. Generated interfaces are particularly prone to the specific failures that are expensive to unpick later: a div behaving as a button, ARIA applied confidently and wrongly, a placeholder standing in for a label, focus that goes nowhere sensible when the route changes.

Performance

State it as a number, at a percentile, under a stated load. "Fast" is not a requirement. "95th percentile under 500 milliseconds at 1,000 concurrent users" is one, and the difference is that the second can fail. Average response time is close to useless as a target, because the average is exactly where your worst experiences hide.

Scale

The number of concurrent users belongs in the brief on day one, not because you will have them, but because the number changes the architecture. A design that keeps session state in process, holds a connection open, or does its work synchronously inside the request is fine for fifty users and cannot be tuned into serving thousands. That is not a performance problem you optimise. It is a different system, and finding out at launch is the most expensive way to find out.

The ML ones nobody lists

If there is a model in the path, several more become non-negotiable. Time to first token matters more than total duration, which makes streaming a requirement rather than a refinement. Non-determinism sits in direct tension with Shneiderman's first rule, so you have to decide where consistency is mandatory and constrain those paths. What happens when the model is slow or unavailable is a design decision, not an incident: it is a third-party dependency whose availability you do not control. Cost per interaction is the one non-functional requirement that gets worse as you succeed, which is the opposite of every other kind of software. And a system that talks to people has to tell them it is not a person, which is now a legal requirement in the EU as well as a decent one.

Why later is so much more expensive than it sounds

Every one of these fails the same way when deferred: the cost is not in adding the feature, it is in the assumptions the rest of the system has already made. Undo needs the data layer to have kept what it overwrote. Accessibility needs the components to have been right before three hundred screens used them. Concurrency needs the request path to have been stateless before every handler assumed otherwise. Streaming needs the whole chain to have been built for it, because one buffering hop in the middle removes the benefit entirely.

None of that is a refactor you schedule. It is the part of the system that was decided on day one, by omission.

Write them as gates, not preferences

The practical fix is small, and it is the same discipline that stops an agent chaining functions and losing the data: state the constraint up front, in a form that can fail, and put it in the brief rather than in a review comment. An agent follows a constraint it was given and will not invent one it was not.

  • Make them machine-checkable wherever you can. An automated accessibility pass at WCAG 2.2 AA in the pipeline, a load test that asserts the percentile target, a lint rule that fails a non-semantic control. A requirement with a check attached is a requirement. One without is a wish, and it will lose to the next deadline.
  • Say the numbers. Concurrent users, percentile latency, cost ceiling per interaction. Vague non-functional requirements are how you get a system that meets all of them at demo scale.
  • Name what may not degrade. Which journeys have to work with the model unavailable, which have to be identical every time, which must never be automated without a person.
  • Ask for the evidence, not the assurance. The test output, the audit result, the load profile. This is the same reason a measure with nobody able to act on it is not a loop: an unverified claim of compliance is decoration.

The short version

The bottleneck has moved. It is no longer how long the build takes; it is how well the thing was specified, because the build now follows the specification with uncomfortable fidelity. Functional requirements describe a demo. The non-functional ones are what turn it into something you can put in front of thousands of people, some of whom use a screen reader, on a bad connection, at nine on a Monday morning.

Write both halves. The second half is the one that decides whether you built a system or a convincing screenshot of one.

Building something this applies to?

Start a conversation