InterviewKata
Software architecture · Level 6: Governance and evolution · Module 26 of 46

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 building inspector who visits every day instead of once. Rules about fire exits, wiring and load-bearing walls are written down, but what keeps a building safe is someone checking, regularly, that nobody blocked the fire exit with boxes. Fitness functions are that inspector, automated, checking every commit.

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:

Kinds of fitness function

KindMeaningExample
Atomic vs holisticChecks one characteristic, or several interacting togetherA layering test vs a load test with security enabled
Triggered vs continuousRuns on an event (a commit, a release), or all the time in productionA dependency test on commit vs latency monitoring with alerts
Static vs dynamicA fixed threshold, or one that depends on context"No cycles" vs "latency target scales with the number of users"
Automated vs manualRun by tools, or by people with a checklistA 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.

250 ms

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:

  1. 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).
  2. 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.
  3. 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).
  4. Did we do a good enough job? Check that each mitigation exists and keeps existing: that's where fitness functions come in.
ThreatProperty brokenArchitectural control
SpoofingAuthenticationSingle sign-on, MFA; service identity with mTLS
TamperingIntegrityTLS everywhere, signed messages and artefacts, append-only audit stores
RepudiationNon-repudiationTamper-evident audit logs of who did what
Information disclosureConfidentialityEncryption at rest and in transit, least-privilege data access, tenant filters
Denial of serviceAvailabilityRate limits, quotas, bulkheads (Module 22)
Elevation of privilegeAuthorisationAuthorisation 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

Two-sentence answers
  • "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.
Red flags interviewers notice
  • 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

Memory hook: "If it isn't checked, it isn't true"Every important architecture decision gets an automated check, or it will quietly stop being true.
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 inspectionArchitecture governance
The building regulationsArchitecture decisions
An inspector every dayFitness functions on every commit
A smoke alarmA continuous production check
The inspection checklistThe compliance section of an ADR

The trap it saves you from

An architecture that exists only in diagrams.

7. Common mistakes

Rules without checksEvery unchecked rule erodes. Pick the few that matter most and automate them.
Flaky fitness functionsA check that fails randomly gets disabled, and then nothing is checked. Baseline, allow variance, and fix flakiness fast.
Only triggered checksStructure can be checked on commit; latency and availability drift in production. Add continuous checks.
Checking everythingHundreds of rules make the architect a bottleneck by proxy. Govern the expensive decisions only.

8. Design exercise (30 minutes)

  1. One per characteristic (15 min). For your top three characteristics, write one fitness function each: what it measures, the threshold, when it runs.
  2. One per decision (10 min). Take two architecture decisions in your system and write the check that would catch a violation.
  3. 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?

It measures the architecture, not the features.

Alerting when production p99 latency exceeds 300 ms for 10 minutes is which kind?

It runs all the time against the live system.

Which is a structural fitness function?

It enforces the layering decision on every build.

Why add a relative rule ("no more than 10% worse than the last release")?

Many small regressions under the limit add up; the relative rule stops each one.

What is fitness-function-driven architecture?

The checks define what "good" means, then guard it.

In a threat model, where should you look hardest for threats?

Crossings between levels of trust (internet to gateway, service to database, to a partner) are where STRIDE threats appear.

10. Go deeper

ResourceTimeWhy
Building Evolutionary Architectures, 2nd edition (Ford, Parsons, Kua, Sadalage)bookThe book that introduced fitness functions for architecture.
ArchUnit user guide30 minWriting structural fitness functions as unit tests.
Threat Modeling Manifesto10 minThe four questions, values and principles of threat modelling.
Threat Modeling Cheat Sheet (OWASP)20 minData-flow diagrams, trust boundaries and STRIDE in practice.
Architectural fitness functions (Thoughtworks Technology Radar)5 minWhy the industry adopted the technique.