Topic: Architecture decision records
Architecture Decision Record Best Practices — What Actually Works After Year One
Most ADR guides cover the format. Few cover why teams write good ADRs for three months and then quietly abandon the practice. This page consolidates the operational disciplines that keep an ADR practice alive: the fields that are never optional, the threshold for when to write, the immutability rule that most teams violate within the first quarter, and the retrospective pattern for catching up on decisions made before ADR adoption. The format is the easy part.
TL;DR
Five rules that determine whether an ADR practice survives year one: (1) Title names the decision, not the problem. (2) Decision is one active-voice sentence. (3) Consequences includes at least one real downside — an ADR with only positive consequences is a press release. (4) Never edit the body of an Accepted ADR; write a new one and supersede the old one. (5) The four-question threshold (durable, cross-team, contested, costly-to-reverse) filters 80% of implementation details that don't warrant an ADR. Format choice and tooling are secondary to these five rules.
The three fields that are never optional
ADR templates range from two fields (LADR: Decision + Consequences) to twelve (TOGAF-mapped with stakeholders, requirements traceability, and governance log references). Regardless of which template your team uses, three fields are non-negotiable at every scale.
1. Title names the decision, not the problem
The most common titling mistake is naming the question instead of the answer. "Database for the new payments service" describes a problem; "Use Postgres for the payments service over MySQL" names a decision. The difference matters for retrieval: when someone is auditing why the team chose Postgres, they search the directory title list for Postgres, not for "database." A decision-framed title is also its own one-line summary — a reader scanning the directory understands what was decided without opening the file.
The pattern for titles that pass the filter: start with a verb in the infinitive that names the chosen option. "Use Kafka for async event delivery." "Adopt MADR format for all new ADRs." "Deprecate the v1 internal API by Q3." The rejected option belongs in the Alternatives section, not the title.
2. Decision is one active-voice sentence
The Decision section is not the place for rationale, alternatives analysis, or trade-off discussion. Those belong in Context and Consequences. The Decision itself should be one sentence in the active voice that names what was chosen. "We will use Kafka for async event delivery between the order and fulfillment services." Not "Kafka was evaluated alongside SQS and RabbitMQ, and after discussion of throughput requirements and operational overhead, the team decided to proceed with Kafka as the primary async transport."
If the Decision section cannot be compressed to one sentence, it is likely describing an implementation plan rather than a durable architecture call. Implementation plans change within weeks; the Decision field needs to remain accurate for 18–24 months without edits. The shorter the Decision, the more durable it is.
3. Consequences includes at least one real downside
An ADR with only positive consequences in the Consequences section is a press release, not an architecture decision record. Every architecture call involves trade-offs; failing to record them produces a directory that reads like marketing copy and tells engineers nothing useful about what constraints the decision creates. The Consequences section is the most important field for future readers — it answers "what did we give up?" and "what do we have to live with?" — and it is the field most commonly left empty or filled with vague optimism.
Consequences should be bounded to architecture impact, not implementation detail. "Kafka introduces an operational dependency on a broker cluster that requires expertise to operate and monitor" is a real consequence. "We will need to set up Kafka" is not. Real consequences are things future engineers will encounter as constraints 12 months later and will want to know were anticipated.
The threshold: when to write an ADR
The four-question decision threshold filters which calls warrant an ADR and which don't. Apply all four questions to the decision:
- Durable? Will this call still matter in 18 months, or is it likely to change with the next refactor?
- Cross-team? Does it affect more than one service, more than one team, or a system boundary that other teams depend on?
- Contested? Was there meaningful disagreement, or at least two plausible options with different trade-off profiles?
- Costly to reverse? If this turns out to be wrong in six months, what does it cost to undo?
A call that scores yes on three or four qualifies. Two yesses is borderline — write a lightweight ADR (LADR format, three fields) if the decision involves an external dependency or a data model choice. One or zero yesses: implementation details belong in the PR description, not the ADR directory.
The threshold question the four-question filter doesn't answer: how many is too many? Teams that apply the threshold correctly write 4–10 ADRs per quarter for a 5–20 person team. More than 15 per quarter at that team size typically signals the threshold is being applied too loosely — the directory is filling with implementation choices that will be superseded within a few months and that no one will read after the sprint ends.
Template selection
Four format families cover the practical landscape. The choice is driven by three questions:
| Template | Choose when | Avoid when |
|---|---|---|
| Nygard (original) | Team is new to ADRs, wants the lowest-friction start. Five sections: Title, Status, Context, Decision, Consequences. | Non-engineer stakeholders need to review ADRs; Status-as-H2-heading is invisible to tooling that reads frontmatter. |
| MADR | Team wants YAML frontmatter for Status, date, and deciders; wants Dataview/tooling compatibility; wants a richer field set without going full TOGAF. | Team is not already using frontmatter-aware tools (Obsidian, static site generators). Adds friction for teams who just want plain Markdown. |
| LADR (lightweight) | Team is resistant to ceremony; decisions are well-understood and the audience is small. Three fields: Title, Decision, Consequences. | Decisions involve multiple stakeholders, cross-service boundaries, or require traceability to requirements. Missing Context section becomes a problem after six months. |
| TOGAF-mapped | Organization is running a TOGAF program and ADRs need to map into the Architecture Repository and Phase H change requests. Seven additional frontmatter fields for EA Domain, ADM Phase, stakeholder mapping. | Teams smaller than ~100 engineers, or any team without an existing TOGAF program. The field set creates overhead that kills adoption at smaller scales. |
Once a team has written its first 10 ADRs in one format, switching formats costs more than the format difference is worth. Pick the simplest format that covers the stakeholder and tooling requirements, and resist the urge to refactor the format itself — format migrations are always more disruptive than anticipated. The storage format comparison covers the separate question of where ADRs live (Markdown in repo, Notion, Confluence, SharePoint).
Numbering and filesystem rules
Three numbering rules prevent the most common directory-management failures:
- 4-digit zero-padded IDs.
0001-use-postgres.md, not001-use-postgres.md. Three digits caps around ADR 999, which most fast-moving teams hit within five years. Five digits is over-specified without buying anything until past ADR 9,999. See the ADR numbering scheme guide for the merge-base allocator recipe that prevents collision under parallel PRs. - Gaps are correct. When a PR that would have created ADR 0047 is closed without merging, the number 0047 is retired permanently. Reusing it poisons every external reference — git history, PR comments, Slack threads, runbook citations — that referenced the original proposed ADR during review. The next ADR after 0046 is 0048, with a visible gap that is correctly read as "a decision was proposed and rejected here."
- Never renumber. Three motivations that recur and should all be rejected: cosmetic gap-cleanup ("let's make the sequence tidy"), padding-migration ("let's switch from 3-digit to 4-digit by renaming"), and fork-prefix ("let's prefix this team's ADRs with B to avoid conflict"). All three destroy external references. The merge-base allocator handles parallel-PR collision; the gap rule handles rejected proposals; monorepo naming conflicts are handled with directory paths, not ID-prefix remapping.
The immutability rule
The most important operational rule in the ADR practice is also the one most commonly violated in the first three to six months: never edit the Context, Decision, or Consequences sections of an Accepted ADR.
The audit trail is the point. When a team hires a new CTO, when an engineer inherits a system, when a post-mortem asks "why did we choose Postgres over DynamoDB?" — the ADR is only valuable if it records what the team knew and believed at the time the decision was made. An in-place edit replaces that historical record with whatever the editor believes is currently true. After one in-place edit, the directory is no longer a reliable archive; it is a document that reflects current beliefs instead of decision history.
The three moves that are always correct instead of in-place edits:
- Notes section for context that evolved without reversing the decision. "As of 2026-03, we migrated from RDS to Aurora; the Postgres choice stands. The operational model changed, not the database choice." A Notes entry is dated, attributed, and bounded — it records the evolution without touching the body.
- Supersession when the decision itself changed. The two-file atomic supersession protocol: write a new ADR with a
Supersedes:field pointing to the old one, change the old ADR's Status to Superseded and add aSuperseded-by:pointer, commit both files in one PR. The CI bidirectional integrity check catches any supersession that leaves a one-sided pointer. - Deprecation when the context became void — the component was removed, the team dissolved, the decision space disappeared — with no named replacement decision. See when to retire an ADR for the Deprecated vs Superseded distinction.
The common scenario that breaks the rule: a new engineer reads an old ADR, finds the Context section describes constraints that have since changed, and opens a PR to "update the ADR." The right move is to add a Notes entry documenting what changed and when, not to edit the Context. Context describes the world as it was at decision time; Notes extends the record forward.
Status lifecycle discipline
The Status field format guide covers placement and companion fields in detail. The lifecycle discipline most teams underinvest in is the legal-vs-illegal transition table:
| Transition | Legal? | Why |
|---|---|---|
| Proposed → Accepted | Yes | Normal ratification path |
| Proposed → Rejected | Yes | Decision made not to proceed; file stays in directory |
| Accepted → Superseded | Yes | New decision reverses the old one; bidirectional pointers required |
| Accepted → Deprecated | Yes | Decision space dissolved; no named successor |
| Accepted → Proposed | No | Cannot un-ratify a decision; write a new ADR if reopening the question |
| Superseded → Accepted | No | Supersession is permanent; the new ADR is what's Accepted now |
| Rejected → Accepted | No (usually) | If the team reverses a rejection, write a new ADR — the context that caused the original rejection should be documented, not overwritten |
The two illegal transitions (Accepted → Proposed, Superseded → Accepted) are the ones teams attempt most often when they want to "reopen" a closed decision without writing a new one. The correct move is always a new ADR: write it with the new Context that explains why the old decision is being revisited, Supersede the old one with a bidirectional pointer, and let the directory show the full history of reversals.
Review process: what CI enforces and what it can't
A well-configured ADR GitHub Action handles the mechanical checks automatically: file structure linting, merge-base-aware auto-numbering to prevent collision, bidirectional supersession integrity, and index rebuilding. These four jobs run on every PR that touches doc/decisions/ with zero human review time.
What CI cannot enforce — and what the ADR review checklist covers — is reasoning quality:
- Context doesn't presuppose the solution. A Context section that describes the constraints in terms that make only one option viable isn't context; it's advocacy. The reviewer catches this; the linter doesn't.
- At least two alternatives are named with real rejection rationales. "We also considered X but went with Y" without explaining why X was rejected is less useful than no alternatives section at all. The review gate asks: would a reader understand why the rejected option was insufficient for these specific constraints?
- Consequences includes at least one negative. CI can check that the Consequences section is non-empty; it cannot check whether the content is honest.
- Atomic supersession when applicable. If the PR introduces an ADR that supersedes a prior one, both files should be in the same PR. A missing Superseded-by pointer in the old file is a review failure even if the new file has a valid Supersedes pointer — the CI bidirectional check catches this at merge, but reviewers should catch it earlier.
The most common review failure is blocking on decision disagreement rather than reasoning quality. The reviewer's job is to ensure the ADR faithfully records the decision that was made and the reasoning that supported it — not to re-litigate whether the decision was correct. A reviewer who blocks the ADR because they disagree with the choice is misunderstanding the review surface; that disagreement belongs in a new Proposed ADR that supersedes the current one, not in a blocking review comment on the record.
Team adoption: the retrospective-first approach
The ADR adoption guide covers the full rollout playbook. The single most effective technique for teams that have failed to adopt ADRs after one or two attempts is the retrospective-first approach: write one ADR about a real, recent, consequential decision before asking for any team commitment to the practice.
The retrospective ADR does two things simultaneously. First, it produces a concrete artifact — not a template, not a process document, but a real record of a real decision the team will remember — that demonstrates the value of the practice to a skeptical audience. Second, it surfaces the gap: most retrospective ADRs reveal that the team's recollection of the decision context differs across team members, that alternatives considered at the time are already forgotten, and that the constraints documented in the ADR weren't written anywhere else. That gap is the argument for the practice, made concrete.
The adoption failure mode to avoid: requiring ADRs for every future PR before the team has internalized the threshold. Blanket requirements produce low-quality ADRs written to satisfy the requirement rather than to record the decision. The practice dies faster than it would have without the requirement. Better: one real ADR, one PR review where the value is visible, one team member who becomes the champion — then the threshold becomes self-regulating.
The retrospective ADR pattern: catching up on unwritten decisions
Most teams that adopt ADRs have 12–36 months of prior decisions with no records. The question of how to address that backlog — without spending weeks on archaeology — is answered differently depending on the tools available.
The most productive source for retrospective ADRs is AI chat exports. Engineers who were using ChatGPT or Claude as thinking partners during architecture calls have a preserved record of the reasoning in their conversation history — even when no ADR was written at the time. The export contains the alternatives considered, the constraints named, the specific objections raised, and the final call — exactly the Context, Decision, and Consequences fields the ADR template asks for.
The retrospective workflow:
- Export your ChatGPT and Claude conversation history (see the ChatGPT export guide and the Claude export guide).
- Run the export through an extractor that identifies decision-shaped exchanges — conversations where options were compared, trade-offs were named, and a direction was chosen.
- Review the extracted records against the four-question threshold to identify which ones warrant a retrospective ADR.
- Use the extracted Context (the problem framing from the conversation), Alternatives (the options discussed), and Consequences (the trade-offs named before committing) as the first draft of each retrospective ADR.
- Date the ADR with the conversation date, not today's date. A retrospective ADR dated accurately is more useful than one that appears to record a decision made last week.
The retrospective ADR is inherently lower-quality than a prospective one: some context is missing, some recollections are imperfect, the constraints aren't as clearly articulated as they would be if written at decision time. Write it anyway. A "best-available reconstruction" record is more useful than no record, and the gap between reconstruction and perfect memory is often smaller than expected when the original chat conversation is the source.
Failure modes: the anti-practices list
The practices that kill ADR adoption in year one, in rough order of frequency:
- In-place editing of Accepted ADRs. The failure mode described above. The first in-place edit signals to the team that the directory is a living document, not an audit trail, and the value of the archive degrades from that point.
- ADR for every PR. Produces low-quality records written to satisfy a requirement, not to capture a decision. The directory fills with noise that obscures the signal. Apply the threshold.
- Decision section as rationale. The Decision field is not the place to explain the reasoning. One sentence naming the chosen option. Rationale belongs in Context (what constraints made this decision necessary) and Consequences (what trade-offs the decision creates). Decision-as-rationale produces records that mix the what and the why in a way that makes neither clear.
- Renumbering for cosmetic reasons. "The gap looks untidy" is not a reason to renumber. Renumbering destroys external references silently — existing citations in git history, PR comments, and runbooks break with no warning. The gap is correct and should stay.
- No negative consequences. As described above: if the Consequences section contains only positives, the reviewer should ask for the real trade-offs before approving. An ADR with only positive consequences is not an honest record of a decision.
- Status variant explosion. Using different Status values across the directory (Accepted, Approved, Ratified, Adopted, Active) because each engineer who wrote an ADR had a different intuition about the right word. The Status format guide covers the canonical values; enforce them with the ADR GitHub Action's structure lint job.
- Title describes the problem, not the decision. "API versioning strategy" describes a topic. "Use URL-path versioning (v1/, v2/) over header-based versioning" names a decision. Titles that describe problems produce a directory that is unsearchable by outcome — you have to open every file to find the one that answers the question.
- No CI enforcement until it's too late. Without the GitHub Action running on every PR, numbering collisions accumulate, Status variants diverge, and supersession pointers go one-sided. Adding CI after the directory has diverged requires a manual cleanup pass that is expensive and often never happens. Add the structure lint job at ADR 0001, even if the only rule it enforces is "non-empty Decision section."
Related questions
How many ADRs should a team write per quarter?
The baseline is 4–10 ADRs per quarter for a 5–20 person engineering team, with significant variance by team maturity and pace. A three-person startup making infrastructure decisions fast might write 10–15 in a quarter during a platform build-out; a 50-person platform team with an Architecture Board might write 4–6 Board-reviewed ADRs plus 20–30 squad-level ones. The calibration signal is whether the decisions that land in a post-mortem as "we never wrote down why we chose X" are passing the four-question threshold (durable, cross-team, contested, costly-to-reverse). If they are, you're writing too few. If the ADR directory is filling with single-service implementation choices that will be revisited in six weeks anyway, you're writing too many.
Should every pull request have an architecture decision record?
No. Most PRs contain implementation details — specific code choices that will be revisited in the next refactor — rather than durable architecture calls. Applying the four-question filter (durable, cross-team, contested, costly-to-reverse) to the decision implied by a PR determines whether an ADR belongs. The ADR GitHub Action's PR template stub makes this question a standard check rather than an afterthought, but the answer is "no" for most PRs. Teams that require an ADR for every PR quickly produce a directory of low-quality records and then abandon the practice within 60 days.
What is the most common reason ADR practices fail after the initial adoption?
Editing the body of Accepted ADRs. When teams revisit a decision and find the rationale outdated, the tempting move is to edit the Context, Decision, or Consequences sections in-place. This destroys the audit trail — after an in-place edit, the ADR no longer records what was true at the time the decision was made. The right moves are: add a Notes section for context that evolved without reversing the decision; write a new ADR that supersedes the old one if the decision itself changed. Once a team edits even one Accepted ADR in-place, engineers stop trusting the directory as a reliable record and the practice degrades.
How do you write ADRs for decisions that were made before the team adopted the practice?
The retrospective ADR pattern: use the decision-capture artifacts that already exist. The most productive source is AI chat exports. Engineers who were using ChatGPT or Claude as thinking partners for architecture calls have a preserved record of the reasoning — alternatives considered, constraints named, trade-offs weighed — even if no ADR was written at the time. Export your conversation history, extract decision-shaped exchanges, and use the extracted records as the first draft of retrospective ADRs. The Context section fills from the problem framing; the Alternatives section fills from the options discussed; the Consequences section fills from the trade-offs named before committing. Date the ADR with the conversation date, not today's date.
Further reading
- When to write an ADR (and when you shouldn't) — the four-question decision threshold in full: durable / cross-team / contested / costly-to-reverse, with a 12-row worked-examples table sorted into yes/no/maybe and the 4–10 ADRs/quarter baseline split by team size.
- ADR lightweight template — LADR, Y-Statements, and the minimum viable format — copy-paste LADR three-field template for teams that resist Nygard ceremony; the Y-Statement one-sentence form; and the contrarian insight that lightweight formats are for prospective ADRs while Nygard-complete is actually easier for retrospective ones.
- How to update an ADR (without breaking the audit trail) — the full 5-state lifecycle machine with legal and illegal transitions named explicitly; the three-step supersession protocol; the Notes-section convention; and the six-bullet "what NOT to do" list.
- ADR supersession pattern — when to supersede, when to annotate, and how to stay bidirectional — the supersede-vs-annotate decision table, the two-file atomic protocol with code blocks in both Nygard and MADR styles, the bidirectional integrity bash script, and the cascade chain flattening rule.
- ADR review checklist — what to look for before merging — 12-item checklist across Structure, Reasoning Quality, Traceability, and Longevity; the automation ceiling table showing which items CI catches vs which require human review; the three common review failures that kill ADR practices.
- The ADR GitHub Action — a CI pipeline for architecture decision records — the 90-line copy-paste workflow with four jobs (structure-lint, numbering, supersession integrity, index rebuild); paths filter; nightly schedule trigger for the supersession check.
- ADR adoption guide — how to introduce architecture decision records to a resistant team — the retrospective-first approach, the two-champion model, minimum viable three-field format, CI enforcement timing, the 60-day adoption threshold, and the objection-handler for skeptical teams.
- ADR numbering scheme — padding, gaps, and collision recovery — the four operational answers (4-digit padding, gaps-are-correct, merge-base-aware allocator, never-renumber discipline) with the failure modes that show up without CI enforcement.
- How to extract decisions from your ChatGPT chats — the buyer-mode pitch page; the extractor recipe with regex patterns and the optional LLM pass; the retrospective ADR workflow from ChatGPT conversation history.
- How to extract decisions from your Claude conversations — the symmetric Anthropic-side extraction guide; the five-step recipe for the simpler flat-array format; Artifact-as-decision-source heuristic; the five metadata fields to preserve.
- ADR directory structure in a monorepo — per-service vs central, numbering, and CI — the structural question this page's best-practices rules assume is settled before applying them: in a monorepo, which directory does an ADR belong to? The monorepo guide covers the central vs per-service vs hybrid patterns, numbering collision strategies, CI paths-filter configuration, and the cross-cutting decision placement rule (which connects directly to the "cross-team" question in the four-question threshold).
- ADR decision authority matrix — who writes, reviews, and approves — the governance practice that determines whether "Accepted" status is a meaningful organizational commitment or just the author filing paperwork. The authority matrix assigns a RACI for five decision classes (implementation, service architecture, API contract, data/schema, infrastructure/ops + security-relevant), names the self-approval boundary rule, time-boxes the Consulted review window to prevent indefinite stalling, and calls out the four anti-patterns (self-approval everywhere, over-centralization, treating Consulted as blocking, approval not recorded in the file) that are the most common reasons ADR archives lose credibility after year one.
- ISO 25010 quality attributes in ADRs — tagging decisions for architecture governance — an advanced annotation layer for teams past year one: adding a quality-attributes YAML frontmatter field using the eight ISO/IEC 25010 characteristic names (security, reliability, maintainability, performance-efficiency…) for traceability and governance reporting. The controlled vocabulary prevents the tag proliferation that kills free-form tagging schemes, and the Dataview queries and CI enforcement recipes on that page pair with the GitHub Action CI workflow on this one.