Fitness functions and governance
An architecture decision that isn't checked slowly stops being true. A deadline here, a shortcut there, and the layered system has calls skipping layers, the services call each other synchronously, and p99 latency has crept from 200 ms to 900 ms without anyone deciding it should. Fitness functions are automated checks that an architecture characteristic still holds. They turn the architect's rules from documents nobody reads into tests that fail the build.
1. The idea
A fitness function is any mechanism that gives an objective verdict on whether an architecture characteristic is still met. The term comes from evolutionary computing: it measures how close a candidate is to the goal. Examples:
- A unit test that fails if the presentation layer imports the persistence layer (structure).
- A build step that fails if any package dependency cycle appears (modularity).
- A load test in the pipeline that fails if checkout p99 exceeds 300 ms (performance).
- A nightly check that every service has a runbook, an owner and alerts (operability).
- A chaos experiment that kills an instance in staging and checks error rates stay under 0.1% (resilience).
Kinds of fitness function
| Kind | Meaning | Example |
|---|---|---|
| Atomic vs holistic | Checks one characteristic, or several interacting together | A layering test vs a load test with security enabled |
| Triggered vs continuous | Runs on an event (a commit, a release), or all the time in production | A dependency test on commit vs latency monitoring with alerts |
| Static vs dynamic | A fixed threshold, or one that depends on context | "No cycles" vs "latency target scales with the number of users" |
| Automated vs manual | Run by tools, or by people with a checklist | A licence scanner vs a legal review of a new dependency |
Fitness-function-driven architecture goes one step further: when you choose the top characteristics (Module 04), you write their fitness functions at the same time, before the design. They become the definition of "done" for the architecture, and the guard against drift afterwards.
2. How it works
Fitness functions in the pipeline and in production
Drift, with and without a check
The decision: "Orders never calls Payments synchronously; it publishes an event." Watch eight months of releases.
3. Try it yourself
Tune a performance fitness function
Checkout's p99 latency is measured by a load test in every build. Choose the threshold and how strict the rule is, and see which of the last twelve builds would have failed, and the code for the check.
4. Trade-offs
Strict vs noisy
Tight thresholds catch drift early and fail builds for noise. Loose ones never fail. Set limits from measured baselines, allow for variance, and fix flaky checks quickly or people learn to ignore them.
Absolute vs relative
An absolute limit protects users; a relative one catches each regression when it's small, even under the limit. Many teams use both.
Pipeline vs production
Pipeline checks are cheap and block bad changes early but can't see real load. Production checks see reality but only after the fact. Use triggered checks for structure, continuous ones for operational characteristics.
Governance vs autonomy
Fitness functions enforce the rules that cross teams and leave everything else to the team. Too many and the architect becomes a gatekeeper again, by tool.
5. In real projects
Architecture as code. Rules like "only the api package of a module may be used by others" can be written in ArchUnit (Java), NetArchTest (.NET), dependency-cruiser (JavaScript) or import-linter (Python), and run as ordinary tests. Some teams write them in a small declarative language, so architects can read and review the rules without reading test code.
Start with the decision records. Each architecture decision record (Module 27) can carry a "compliance" section: how will we know this decision is still followed? That's where fitness functions come from.
Governing constraints, not code style. Use fitness functions for decisions that are expensive to violate: layering, dependency directions, data ownership, performance budgets, security baselines. Leave formatting and naming to linters.
Security as a characteristic: threat modelling
Security is an architecture characteristic like any other, but it can't be load-tested into shape. The design has to be analysed for what could go wrong, and the answers turned into controls and checks. That analysis is threat modelling, and the Threat Modeling Manifesto frames it as four questions:
- What are we working on? Draw the system as a data-flow diagram: processes, data stores, external actors, the flows between them, and the trust boundaries where data crosses from one level of trust to another (internet to gateway, service to database, your system to a partner's).
- What can go wrong? Walk every element and every flow that crosses a boundary with a prompt list. The most common is Microsoft's STRIDE, one letter per security property an attacker could break.
- What are we going to do about it? For each threat: mitigate it, remove the feature, transfer the risk, or accept it on record (an ADR, Module 27).
- Did we do a good enough job? Check that each mitigation exists and keeps existing: that's where fitness functions come in.
| Threat | Property broken | Architectural control |
|---|---|---|
| Spoofing | Authentication | Single sign-on, MFA; service identity with mTLS |
| Tampering | Integrity | TLS everywhere, signed messages and artefacts, append-only audit stores |
| Repudiation | Non-repudiation | Tamper-evident audit logs of who did what |
| Information disclosure | Confidentiality | Encryption at rest and in transit, least-privilege data access, tenant filters |
| Denial of service | Availability | Rate limits, quotas, bulkheads (Module 22) |
| Elevation of privilege | Authorisation | Authorisation checked in every service, not only at the gateway |
Two principles shape the controls. Zero trust: being inside the network grants nothing; every call proves its identity and is checked against policy (NIST SP 800-207). Privacy by design: collect the minimum personal data, keep it for the minimum time, and make protection the default, which the GDPR requires as "data protection by design and by default" (Article 25). Both are architecture decisions: where identity is checked, which services may see personal data, how deletion reaches every copy.
Security fitness functions keep the answers true: a dependency scan that fails the build on a known critical vulnerability, a policy-as-code check that rejects a public storage bucket or a service without mTLS, a test that every endpoint requires authentication. The mechanisms themselves (tokens, encryption, zero-trust proxies) are in the System design Module 26: security.
Say it in the interview
- "What's a fitness function?" An automated, objective check that an architecture characteristic still holds, like a test that fails on a forbidden dependency or a load test with a latency limit. It keeps the architecture from drifting.
- "How do you make sure teams follow architecture decisions?" Explain the reason, then automate the check: every decision record has a compliance section, and where possible a fitness function in the pipeline.
- "How do you design for security?" Threat-model the design: draw the data flows and trust boundaries, walk each crossing with STRIDE, and decide a control for each threat. Then automate the important controls as fitness functions, so they stay in place.
- "Triggered or continuous?" Triggered checks on commit for structure and dependencies; continuous checks in production for latency, availability and error budgets.
- Architecture rules that live only in a wiki page.
- A performance target that's never measured until production.
- Fitness functions so flaky that teams disable them.
6. Remember it
How this hook works: what "if it isn't checked, it isn't true" means
What the slogan means, phrase by phrase
- "If it isn't checked"
- A rule without a fitness function depends on everyone remembering it under pressure.
- "it isn't true"
- Within months, the code will differ from the decision.
Why this picture fits: it's the lesson of every architecture review that finds the system no longer matches its diagrams.
The story → the concept
| Building inspection | Architecture governance |
|---|---|
| The building regulations | Architecture decisions |
| An inspector every day | Fitness functions on every commit |
| A smoke alarm | A continuous production check |
| The inspection checklist | The compliance section of an ADR |
The trap it saves you from
An architecture that exists only in diagrams.
7. Common mistakes
8. Design exercise (30 minutes)
- One per characteristic (15 min). For your top three characteristics, write one fitness function each: what it measures, the threshold, when it runs.
- One per decision (10 min). Take two architecture decisions in your system and write the check that would catch a violation.
- Pick the first (5 min). Which one would you automate this week, and where in the pipeline?
9. Self-check quiz
What is a fitness function?
Alerting when production p99 latency exceeds 300 ms for 10 minutes is which kind?
Which is a structural fitness function?
Why add a relative rule ("no more than 10% worse than the last release")?
What is fitness-function-driven architecture?
In a threat model, where should you look hardest for threats?
10. Go deeper
| Resource | Time | Why |
|---|---|---|
| Building Evolutionary Architectures, 2nd edition (Ford, Parsons, Kua, Sadalage) | book | The book that introduced fitness functions for architecture. |
| ArchUnit user guide | 30 min | Writing structural fitness functions as unit tests. |
| Threat Modeling Manifesto | 10 min | The four questions, values and principles of threat modelling. |
| Threat Modeling Cheat Sheet (OWASP) | 20 min | Data-flow diagrams, trust boundaries and STRIDE in practice. |
| Architectural fitness functions (Thoughtworks Technology Radar) | 5 min | Why the industry adopted the technique. |