Skip to content

Three Kinds of Requirement

Module 1 established what the business wants moved. Nobody has yet said what the system must be like, and when they do it will arrive as a long undifferentiated list.

This topic sorts that list into three kinds, then applies the filter that matters: which of them will cost you a rebuild if you get them wrong.

A functional requirement says what the system does. Answer a customer’s question about scheduling. Reschedule a job. Hand the conversation to a person. These are the ones everybody volunteers, because they are what the system is for.

A quality attribute says how well it does it. Fast, available, accurate, cheap, secure, changeable. Every quality attribute is a property of the whole, not of one function.

A constraint is a decision already made for you. A regulation. An existing database you must use. A deadline somebody promised a customer. Constraints are not negotiable trade-offs; they are the shape of the box you design inside.

The distinction earns its keep because the three behave differently under change:

Kind Changing it usually costs you
Functional requirement Code. Another endpoint, another branch.
Quality attribute Structure. Where things sit, what talks to what.
Constraint Nothing — you cannot change it. You can only discover it late.

That middle row is the reason requirements engineering is an architect’s problem rather than a product manager’s. Functions mostly fill a structure. Qualities mostly determine it.

One caution: the sorting is a means, not an end. Teams can spend an afternoon arguing whether “must work offline” is a function or a quality. If an argument about the label is not changing a design decision, pick one and move on.

An Architecturally Significant Requirement — an ASR — is one whose satisfaction constrains the structure. If you had it wrong, you would restructure, not patch.

Three tests, applied in order:

graph LR
  FR["Functional<br/>what it does"] --> F{"Would getting this<br/>wrong force a<br/>restructure?"}
  QA["Quality attribute<br/>how well it does it"] --> F
  C["Constraint<br/>already decided"] --> F
  F -->|yes| ASR["Architecturally<br/>significant<br/><i>design around these</i>"]
  F -->|no| REST["Everything else<br/><i>still build it, just<br/>don't design around it</i>"]

  classDef drained fill:#D8D3CB,stroke:#B8B2A8,stroke-width:2px,color:#3F3F3F
  classDef live fill:#E8A33D,stroke:#C4832A,stroke-width:2px,color:#ffffff
  classDef key fill:#D9695B,stroke:#B4483A,stroke-width:2px,color:#ffffff
  class FR,REST drained
  class QA,C,F live
  class ASR key

The filter runs on all three kinds, but the amber boxes are where it fires most often. Functions reach the significant set only by exception.

Test 1 — the structural test. Does satisfying it force a decision about what goes where? A requirement that data must never leave a region forces a topology. A requirement that responses stream forces a transport choice end to end. A requirement that the assistant greets the user politely forces nothing.

Test 2 — the cost-of-being-wrong test. Imagine learning about it in month seven. Is that a fix, or a rebuild? The requirements that are expensive to discover late are the same ones that are cheap to accommodate early, which is the whole argument for caring now.

Test 3 — the spread test. Does it cut across components and teams? Anything that has to hold everywhere — a cost ceiling, an audit trail, a latency budget — is structural almost by definition, because it cannot be satisfied in one place.

Three recurring hiding places, all of which look like background information rather than requirements:

Inside constraints that read as facts. “We’re in two regions” sounds like an infrastructure note. If contracts forbid data crossing between them, it is the single most structural thing anyone has told you.

Inside volumes. A function described without a number is not yet a requirement. The same function at ten requests a day and ten thousand an hour is two different architectures. A functional requirement becomes architecturally significant through its scale or its mode, which is why the two kinds cannot be fully separated.

Inside what must never happen. Stakeholders describe desired behaviour fluently and forbidden behaviour not at all. Asking “what must this never do?” surfaces constraints that no amount of asking “what should it do?” will reach.

Sorting and filtering takes real time before anyone sees a design, and in a company with no architecture practice that reads as delay. You will be asked why you are not drawing boxes yet.

The defensible answer is the one from Module 1: a structure that satisfies the wrong requirements is competent work aimed at the wrong target. But the cost is real, and the mitigation is to work in a timebox — a first pass in days, not weeks, explicitly labelled as a first pass.

This topic feeds the requirements catalog and the ASR list. Sort everything you can find; mark the significant ones; and for each, write the reason it is significant. The reason is the artifact — a list of ASRs with no justification is an opinion with formatting.


→ You can spot the requirements that matter. But “the cost per interaction must be low” is still untestable — how do you write one so it can be checked? — Quality attribute scenarios