Architectural Fitness Functions
Why this chapter matters
- Converts architecture goals into executable or reviewable checks.
- Keeps quality constraints visible after the initial design conversation.
- Helps teams scale standards without requiring architects to review every line manually.
Core mental model
A fitness function is a test, metric, rule, or review gate that tells you whether the system still satisfies an architectural property. In frontend systems, useful fitness functions often guard performance, accessibility, dependency boundaries, security headers, rendering behavior, and observability.
Examples:
- no route exceeds its JavaScript budget
- design-system components pass keyboard and screen-reader contract tests
- feature modules cannot import across forbidden boundaries
- pages set required security headers
- route loads emit standard telemetry
- critical flows have E2E coverage
Fitness functions should be close to the risk. A module boundary can be checked by linting. A stale-response bug may need integration or E2E coverage. A Core Web Vitals target needs both lab and field measurement.
Decision framework
| Architecture property | Fitness function | Tooling level |
|---|---|---|
| Performance | Route bundle and Web Vitals budgets | CI plus RUM |
| Accessibility | Component interaction tests and axe checks | Unit, Storybook, E2E |
| Security | CSP/header checks and dependency audit | CI and deployment |
| Modularity | Import boundary rules | Lint |
| Reliability | Error-free sessions and journey success | Production telemetry |
Implementation patterns
- Start with the failure mode: define the bug or drift you want to prevent.
- Choose the cheapest reliable signal: lint when static analysis is enough; test behavior when static rules cannot prove it.
- Make ownership explicit: a failed fitness function must route to a team.
- Ratcheting beats perfection: when a legacy app is already over budget, prevent it from getting worse and tighten over time.
Atlas example
For Atlas reports:
- filter state that affects data must be URL-backed
- report routes must emit
report_view_loadedandreport_filter_changed - route chunks must stay below the report-route budget
- stale responses must not replace newer responses
- filter controls must be keyboard operable
These are architecture decisions expressed as checks, not reminders.
Anti-patterns and failure modes
- A dashboard nobody owns: metrics exist but do not change behavior. Prevention: assign route and platform ownership.
- Too many gates too early: teams bypass noisy checks. Prevention: start warning-only, then block when stable.
- Static checks for dynamic risks: lint rules cannot prove user journey success. Prevention: match test level to risk.
- Perfect target, no migration path: legacy code fails forever. Prevention: ratchet from current baseline.
- Architecture by documentation only: standards are written but not enforced. Prevention: turn key standards into fitness functions.
Verification checklist
- The fitness function maps to a named architecture property.
- The signal is reliable enough for its enforcement level.
- False positives have an owner and triage path.
- Legacy exceptions have expiration or ratchet rules.
- Results are visible to teams, not only platform maintainers.
Metrics and scorecards
Leading indicators:
- percentage of standards with automated or reviewable checks
- number of failing checks by owner
- time to resolve failed fitness functions
Lagging indicators:
- drift from intended architecture
- escaped defects in guarded areas
- manual review load for architecture-sensitive changes
Exercises
- Define three fitness functions for frontend performance, accessibility, and module boundaries.
- Convert one written architecture standard into a CI or review check.
- Design a ratcheting plan for a route that is currently over budget.