Architecture Decision Records (ADRs): Format and Purpose
What This Concept Is
An Architecture Decision Record (ADR) is a short, dated markdown file that captures one architecturally-significant decision, the forces that led to it, and the consequences. The canonical format from Michael Nygard's 2011 post has four sections:
- Context -- the forces at play, described neutrally
- Decision -- what you decided, stated as "We will..."
- Status -- proposed / accepted / superseded
- Consequences -- what is now easier, harder, riskier, or cheaper
An ADR is one page. It is stored in the repository (typically library/raw/adr/NNNN-title.md), numbered monotonically, and never rewritten in place -- a superseded ADR is kept and the new one references it.
Why It Matters Here
Code answers what. ADRs answer why. Six months later, when someone asks "why are we on Postgres instead of MongoDB?" or "why is authentication a library, not a microservice?", the ADR is the thing that prevents someone from silently reversing the decision without knowing what it was buying.
ADRs are not bureaucratic governance artifacts. They are memory. Teams without them burn time re-litigating decisions every time someone new joins.
Concrete Example
# ADR 0007: Adopt Postgres as the primary relational store
Date: 2026-03-11
Status: Accepted
Supersedes: ADR 0002 (MySQL)
## Context
We currently run MySQL 5.7 for the checkout service. Three forces pull on us:
- We need JSONB-style flexible columns for the new promotions feature.
- Analytics queries on large orders tables are timing out under MySQL's planner.
- The team has stronger Postgres operational experience from prior roles.
MySQL can serve the immediate need with effort, but would require manual JSON
handling and continued planner tuning.
## Decision
We will move the checkout service's primary store to Postgres 15. Migration
will use logical replication with a dual-write cutover window of two weeks.
## Consequences
Positive:
- Native JSONB support removes a layer of custom code.
- Analytics queries run an order of magnitude faster on existing test data.
- Team operational fluency aligns with tooling.
Negative / risks:
- Two weeks of dual-write complexity during migration.
- Existing ORM query hints tied to MySQL will need audit.
- We lose group replication, which we were not using but had assumed as a
future option.
Follow-ups: ADR-0008 will cover connection pool and PgBouncer choice.
Common Confusion / Misconception
"ADRs are design documents." They are not. A design document describes a feature. An ADR describes a single decision. One design doc can reference five ADRs; each is atomic.
"ADR-bureaucracy." Teams who require an ADR for every line of code abandon them quickly. The rule is: ADR for decisions that are architecturally significant -- they affect structure, dependencies, non-functional properties, or are hard to reverse.
"Edit the old ADR." Almost never. Decisions have dates and status. If the decision changes, write a new ADR that supersedes the old one. The history is part of the value.
"ADR = essay." One page. Alternatives section optional but useful. Anything longer than two pages probably wants to be a design document that cites an ADR.
"We know already." If you are the only engineer on the project today, the reader of the ADR is a future you or the next hire. They do not know.
How To Use It
Write an ADR when:
- the decision is hard to reverse (database choice, language, auth model)
- the decision will be questioned later ("why is this a queue, not a cron?")
- multiple credible alternatives exist
- the decision crosses team boundaries
Skip an ADR when:
- it is easily reversible (internal class organization, naming)
- there is only one credible option (use the language's standard library)
- it is already documented adequately somewhere else
Template (full minimal):
# ADR NNNN: <short noun phrase>
Date: YYYY-MM-DD
Status: Proposed | Accepted | Superseded by ADR MMMM
## Context
[Forces, neutral tone]
## Decision
We will ...
## Alternatives Considered (optional, strongly recommended)
- <option>: <why not>
## Consequences
Positive: ...
Negative / risks: ...
Follow-ups: ...
Store in library/raw/adr/. Link from the module's README or design doc. Reference from PR descriptions: "Implements ADR-0007."
Check Yourself
- Why do you leave the superseded ADR in place instead of editing it?
- What is the difference between a design document and an ADR?
- Name a decision you have made (or seen) that would have benefited from an ADR.
Mini Drill or Application
Pick a real decision -- your choice of framework, the authentication mechanism, the decision to use (or not use) a pattern -- and draft a full one-page ADR in the template. Include at least one alternative with a reason for rejection.
Read This Only If Stuck
- Clean Code: How would you build a city
- Clean Code: Scaling up, cross-cutting concerns
- Good Code Bad Code: How code becomes software
- External: adr.github.io -- Architectural Decision Records overview
- External: Nygard: Documenting Architecture Decisions (original 2011 post)
- External: joelparkerhenderson/architecture-decision-record -- templates and examples