Architectural Drift and How Decisions Age
What This Concept Is
Architectural drift is the gap that opens between the decisions the team recorded and what the running system actually does. Decisions age two distinct ways:
- Context drift. The world changed; the decision no longer matches the constraints that motivated it.
- Implementation drift. The decision is still valid; the implementation has diverged from it.
Both are corrosive, in different directions. Context drift means the ADR is obsolete and silently misleads. Implementation drift means the ADR is accurate but the code no longer complies. Each calls for a different response.
Why It Matters Here
Every ADR you write is also a future liability. If you do not audit the record, someone will believe it long after it has lied, and will build on its conclusion. The habit that prevents this is not perfect foresight - it is periodic drift audits.
Drift is also the feedback loop that tells you whether your fitness functions cover the right claims. If implementation drift shows up in a dimension you have no fitness function for, you have learned something about what to automate next.
Concrete Example
Case A: Context drift.
ADR-0029 (2023): Use DynamoDB for the session store to minimize latency and avoid running Postgres in multiple regions.
2026 reality: Postgres now runs multi-region via Aurora Global Database. Our two-week outage post-mortem identified DynamoDB's eventual consistency as the incident root cause.
Response: supersede ADR-0029 with ADR-0071 (move sessions back to Aurora). Mark ADR-0029 Superseded with link.
Case B: Implementation drift.
ADR-0017 (2024): All cross-service calls must go through the service mesh; direct HTTP is forbidden.
2026 reality: the orders service makes five direct HTTP calls to the billing service, added during an incident in 2025 when the mesh had an outage. The mesh issue was fixed; the bypasses stayed.
Response: do not touch the ADR. File a drift ticket. Write a fitness function that would have caught this in CI. Schedule remediation to align code with the (still correct) decision.
Different drift types produce different write-ups and different remediations.
Common Confusion / Misconception
"If the ADR still reads true, it must be fine." It is easy to miss implementation drift: the document is right, the code is wrong, and nobody reconciles them.
"Obsolete ADRs should just be deleted." See Concept 6: supersede, never delete. Obsolete ADRs are evidence of how thinking evolved.
"Drift is a failure." Drift is inevitable. Unnoticed drift is a failure. The habit that matters is periodic audit, not avoidance.
"We can rely on the fitness functions to catch drift." Fitness functions only catch drift in dimensions they cover. The unmonitored dimensions are exactly where the surprising drift lives.
How To Use It
Run a periodic drift audit - typically quarterly, at least for the top-N ADRs of the system.
For each audited ADR:
- Context still valid? If not, supersede.
- Decision still the best we would make today? If not, write a new ADR proposing a change (even if you choose not to act on it).
- Implementation matches the decision? If not, file drift tickets; consider a new fitness function.
- Consequences still accurate? If an unexpected consequence emerged, append to the ADR as a dated addendum (this is one of the few valid in-place amendments).
Write the audit results up: one short page per cycle, with drift findings and the actions taken. Over a year this becomes your team's memory of how decisions age.
Check Yourself
- For one ADR in your repo, write the drift-audit page: context-valid, decision-valid, implementation-compliant, consequences-current.
- What is the difference between context drift and implementation drift in terms of response?
- Why is deleting obsolete ADRs a governance mistake?
Mini Drill or Application
Pick 3 ADRs from your team's repo (or a public ADR corpus). For each:
- name one risk of context drift you can see without looking at code
- name one candidate implementation drift (where does reality probably not match?)
- propose a fitness function that would have surfaced the drift earlier
- decide whether to supersede, amend, or leave untouched
If your repo has no ADRs, audit the implicit decisions instead - the system still has them; they are just not written down.