Design Patterns · Principal Track
The one-page ADR: context, decision, consequences
The Architecture Decision Record is the cheapest tool in architecture — a one-page record of one significant decision, its context, and its consequences. One page isn’t a constraint; it’s the forcing function that makes you find the actual decision.
Scope: the ADR pattern (Michael Nygard, 2011) and the operational practice that makes it stick, with one real ADR written in full. Tooling comparisons, RFC-vs-ADR process debates, and design-doc structure are out of scope — different artifacts.
Six months after you centralize egress, a new engineer finds the NAT gateway living in a dedicated inspection account, decides it’s waste — an extra account, extra hops — and “fixes” it by dropping a NAT gateway into every spoke. In one pull request they’ve quietly dismantled the centralized inspection the security team required, because nobody wrote down why it was there. That is decision amnesia, and it is the default state of every architecture whose decisions live in Slack threads and slide decks. The fix is the cheapest tool you own: a one-page record of the decision, its context, and its consequences. Here is how to write one that actually gets read.
TL;DR — the cheapest tool in architecture
- An undocumented decision will be relitigated — or worse, silently eroded by someone who never knew it was load-bearing. The ADR is the cheapest insurance you can buy.
- An ADR records one architecturally significant decision — expensive to reverse, crosses team boundaries, or constrains future choices. Most decisions fail that test, which is exactly why the ones that pass get read.
- The load-bearing sections are Context and Consequences. Context is the world as it was; Consequences must list costs, not just benefits. And Options considered is the section that actually stops relitigation.
- One page is a forcing function. If it needs ten pages, you haven’t found the decision — you’re writing a design doc that hides several ADRs.
- Kept in-repo, reviewed by pull request, superseded not edited — used this way, an ADR log scales your judgment to teams you’ll never meet. That’s architecture as institutional memory, not decree.
The problem: decision amnesia
That NAT-gateway story isn’t a one-off; it’s the default, and it wears three faces. Relitigation: every time a skeptic joins, the settled argument reopens, because “we discussed this already” is written nowhere they can find. Cargo-culting: new joiners inherit rules with no reasons attached, so they either copy them into places they don’t belong or quietly route around them. Erosion — the worst one: a constraint nobody documented gets “optimized away” by someone who never knew it was load-bearing, exactly as the egress inspection did. Slack threads scroll off; slide decks get archived; the whiteboard gets wiped. A decision survives only if you write it down where the next person will actually look.
What an ADR is — and is not
An Architecture Decision Record is a point-in-time record of one architecturally significant decision — numbered, and immutable once accepted (you supersede it, you don’t edit it). It is deliberately not several nearby things. Not a design doc, which is the how — the mechanism, the interfaces, the diagrams. Not a runbook, which is how to operate the thing once it exists. And not a standard: a standard is a rule you must follow, while an ADR is the reasoning behind one choice — a standard may cite several ADRs as its justification.
The filter for “architecturally significant” is the one-way-door test: a decision earns an ADR if it is expensive to reverse, crosses team boundaries, or constrains future choices. Most decisions fail it — which font, which JSON library — and that’s the point. Because you don’t write one for everything, the ones that exist are worth opening.
| Artifact | Answers | Lifetime |
|---|---|---|
| ADR | Why we chose this | Immutable · superseded, not edited |
| Design doc | How it works | Living · edited |
| Runbook | How to operate it | Living · edited |
| Standard | What you must do | Living · may cite ADRs |
The anatomy, section by section
Five sections, no more. Title and status. A short noun phrase — “ADR-014: Centralized egress inspection” — and a status that is a lifecycle, not a label: Proposed, then Accepted, then one day Superseded-by-ADR-NNN. That lifecycle is what turns a pile of documents into a system you can trust.
Context. The forces at play — constraints, requirements, and the politics, stated diplomatically. “The security team requires centralized inspection” is context, not a complaint. Write it so a reader two years from now understands the world as it was, not as it is now. This is the hardest section to write and the most valuable to read; it is not “we needed a database,” it is the specific pressures that made the choice non-obvious.
Decision. One declarative sentence, active voice: “We will run all egress through a dedicated inspection account.” No hedging, no “we could,” no “we propose to consider.” If you can’t say it in one sentence, you have more than one decision.
Consequences. Both directions — what gets better and what gets worse or harder — plus what you’re explicitly deferring. An ADR that lists only benefits is a sales document, and a reader who catches one selling learns to distrust the whole log. The costs are what make it credible.
Options considered. The compressed version: one line per rejected option and its killing reason. This is the section that actually stops relitigation — the person who shows up asking “why didn’t we just use X” finds X, and its cause of death, already on the page.
A real ADR, in full
Abstract anatomy is easy to nod along to. Here is a real one — a decision to pull shared network infrastructure out of our account-vending pipeline — written the way I’d commit it.
ADR-021: Manage network infrastructure in a dedicated pipeline, separate from AFT
Status: Accepted (2026-03-02) · supersedes nothing
Context. Account Factory for Terraform (AFT) vends accounts and applies each account’s baseline — guardrails, IAM, logging. Shared network changes (Transit Gateway routes, centralized-egress rules, Route 53 Resolver config) were riding the AFT customization pipeline, because that pipeline already held the cross-account access. That coupling meant every network change was gated on AFT’s account-vending cadence and release windows; the networking team could not ship a route change without a platform-team merge; and one bad network commit could block account vending for the whole org. The networking team carries a connectivity SLA but did not own the pipeline that shipped it.
Decision. We will manage shared network infrastructure through a dedicated CodePipeline owned by the networking team, separate from AFT.
Consequences. Better: the networking team ships on its own cadence; network blast radius is separated from account vending; the pipeline’s permissions scope to network resources only. Worse / harder: a second cross-account pipeline to maintain and secure; ordering between account creation (AFT) and network attachment (new pipeline) now needs an explicit hand-off instead of being implicit in one pipeline. Deferred: we are not moving per-account network baseline out of AFT — only shared, central network infrastructure.
Options considered.
— Keep network changes in AFT — rejected: couples network cadence to account vending, gives the networking team no independent release control.
— Manual Terraform apply by the network team — rejected: no review gate, no audit trail, drifts from GitOps everywhere else.
— One shared “platform” pipeline for both — rejected: same coupling as AFT, with a bigger blast radius.
That’s the whole thing — one screen. The “options considered” is three lines, and each one pre-empts a “why didn’t we just…” before it’s asked.
Why one page
One page isn’t a style preference; it’s a forcing function. If the decision needs ten pages, you haven’t found the decision — you’re writing a design doc that secretly contains several ADRs, each its own one-pager waiting to be extracted. The discipline of one page is what separates the decision (which belongs in an ADR) from the mechanism (which belongs in a design doc). And there’s a plainer reason: long documents don’t get read, and an unread decision record protects nothing. This is the Pyramid Principle — Barbara Minto’s — applied to a single choice: lead with the decision, support it with just enough context.
The operational side
Most ADR advice stops at the template. The part that decides whether the practice survives is operational. Keep them in the repo, next to the code the decision governs (docs/adr/0021-network-pipeline.md) — not in Confluence, where they rot unlinked from the thing they describe. Review by pull request, so the decision gets the same scrutiny as the implementation and the PR thread becomes part of its provenance. Number them sequentially and never reuse a number; the number is the stable citation (“see ADR-021”), and an index file keeps them discoverable. Anyone writes; a defined forum accepts — writing is open, accepting is governed. And supersede in the open: the new ADR references the old, the old one gets a forward pointer and stays in the tree. You never delete — the log’s whole value is that it shows how the thinking changed.
| Failure mode | What it looks like | Fix |
|---|---|---|
| Justification theater | ADR written after the fact to rationalize a done deal | Write it while the decision is live — in the PR that makes it |
| ADR-everything | An ADR for the logging library; death by process | Apply the two-question test — most things don’t qualify |
| Empty context | “We needed a database.” | Name the specific forces — load, team, deadline, politics |
| Cost-free consequences | Only benefits listed | List what got worse — that’s what makes it trusted |
ADRs as an influence instrument
Here is the part that earns the practice a place on a principal’s résumé rather than a wiki. A decision log is how you scale your judgment beyond the rooms you’re in. You are not in the design review in two years; the ADR is. Teams you have never met inherit your reasoning — not just your rules — and reasoning is the thing that travels. This is the actual mechanism behind “standards other teams adopted”: they didn’t adopt your decree, they read your context and consequences, agreed with the logic, and applied it themselves. That is the difference between architecture as decree — rules handed down, resented, quietly eroded — and architecture as institutional memory — reasoning handed down, understood, and extended. The one-page ADR is the cheapest instrument you have for the second kind.
The template, and the two-question test
Steal this. Fill the blanks; delete the guidance as you go.
# ADR-NNN: <short decision title>
Status: Proposed | Accepted (date) | Superseded by ADR-MMM
Date: YYYY-MM-DD
Context: The forces at play — constraints, requirements, politics —
written so a reader in two years understands the world as
it was. Not "we needed a database"; the specific pressures
that made this choice non-obvious.
Decision: One declarative sentence, active voice. "We will ..."
Consequences:
Better: what improves
Worse: what gets harder or more expensive
Deferred: what we are explicitly not deciding yet
Options considered:
- <Option A> — rejected because <killing reason>
- <Option B> — rejected because <killing reason>
The ADR will never be the most impressive thing you produce. It is only the cheapest — and, years later, often the most read.
References
- Michael Nygard — Documenting Architecture Decisions (Cognitect, Nov 15 2011), the origin of the ADR: cognitect.com/blog/2011/11/15/documenting-architecture-decisions
- Martin Fowler — Architecture Decision Record (bliki): martinfowler.com/bliki/ArchitectureDecisionRecord.html
- Community hub & templates (MADR, Nygard): adr.github.io
- Barbara Minto — The Pyramid Principle (lead with the answer; support with structure).