Architecture Decision Records: Document Why, Not Just What

Architecture Decision Records: Document Why, Not Just What
Daniel Marsh · Spec-first engineering notes

Six months from now, someone on your team will stare at the codebase and ask, "Why did we choose Kafka over SQS?" or "Why is this a separate service instead of a module?" If the answer lives only in the head of the person who made the call, and that person has moved teams or left the company, the question becomes unanswerable. Architecture Decision Records exist to prevent that. They are short documents that capture not what was built, but why it was built that way.

Published on 2026-02-03 · Updated 2026-05-06 · 10 min read · Author: Daniel Marsh · Review policy: Editorial Policy

The problem ADRs solve

Every codebase is the result of hundreds of decisions. Most of them are small and obvious in hindsight. But a meaningful number are judgment calls where the team weighed trade-offs, debated alternatives, and picked an approach that was not the only reasonable option. The code itself records which option was chosen. It does not record which options were rejected, or why.

This becomes a problem at predictable moments. A new team member joins and questions an architectural pattern. A performance issue surfaces and the team considers refactoring, unaware that the current design was chosen specifically to avoid a different, worse performance issue. A dependency upgrade breaks something, and nobody remembers why the team pinned to an older version in the first place. In each case, the missing piece is the same: the reasoning behind the original decision.

An Architecture Decision Record is a short document, typically one page, that captures that reasoning at the time the decision is made. The concept was formalized by Michael Nygard, and the format has since been adopted widely across engineering organizations. The idea is not new. What is new, for most teams, is actually doing it consistently.

The ADR template

An effective ADR has five sections. Each one is short, and the entire document should fit in a single screen of text. If it does not, you are writing too much.

# ADR-017: Use PostgreSQL for the billing ledger

## Status
Accepted (2026-03-14)

## Context
The billing service needs a persistent store for transaction records.
We evaluated PostgreSQL, DynamoDB, and CockroachDB. The ledger requires
strong consistency, complex queries for reconciliation reports, and
support for row-level locking during concurrent invoice generation.

## Decision
We will use PostgreSQL 16 with the existing RDS infrastructure. The
operations team already maintains PostgreSQL clusters, and the query
patterns match relational modeling well. DynamoDB was rejected because
reconciliation queries require joins across multiple entity types.
CockroachDB was rejected because our current traffic volume does not
justify the operational complexity of a distributed SQL database.

## Consequences
- Positive: familiar technology, strong ecosystem, existing runbooks
- Positive: reconciliation reports can use standard SQL joins
- Negative: vertical scaling limits if transaction volume exceeds
  10M rows/month (revisit if growth projections change)
- Negative: no built-in multi-region replication without third-party
  tooling (acceptable for current single-region deployment)

## Related
- Tech spec: /docs/specs/billing-ledger-v2.md
- Capacity analysis: /docs/analysis/billing-volume-projections.md

The Status field tracks the lifecycle: proposed, accepted, deprecated, or superseded (with a link to the replacement). Context describes the forces at play, not the solution. Decision states the choice and names the alternatives that were rejected, with reasons. Consequences lists both the good and the bad, because every architectural decision involves trade-offs. The optional Related section links to specs, tickets, or analysis documents.

How ADRs complement specs

A technical spec defines what is being built and how. It covers requirements, acceptance criteria, system design, API contracts, and rollout plans. An ADR captures why a particular approach was chosen over the alternatives. These are different documents with different audiences and different lifespans.

Specs are consumed primarily during implementation. Once the feature ships, the spec is mostly historical. ADRs are consumed primarily after implementation, when someone needs to understand why the system looks the way it does. A spec answers "what are we building?" An ADR answers "why did we build it this way?"

In a spec-first workflow, both documents are written before code. The spec goes through review to validate the what and how. The ADR goes through review to validate the why. Teams that write specs but skip ADRs end up with well-documented implementations that lack documented rationale. Six months later, the spec tells you the billing service uses PostgreSQL. The ADR tells you why it does not use DynamoDB.

What decisions are worth recording

Not every decision needs an ADR. Writing one for "we used React" when the entire frontend is already React adds no value. The bar is: would a reasonable senior engineer, looking at this system for the first time, ask "why did you do it this way?" If yes, write an ADR. If no, skip it.

Decisions that typically deserve an ADR:

Decisions that typically do not need an ADR:

The judgment here is about anticipated future confusion. If a future reader would not question the decision, it does not need a record.

Where to store ADRs

There are two practical options: in the code repository or in a wiki. Both work, and the right choice depends on your team's workflow.

In-repo storage (e.g., /docs/adrs/) has clear advantages. ADRs are versioned alongside the code they describe. They go through the same review process as code changes. They are discoverable via grep and IDE search. They cannot drift from the codebase because they live in the same repository. The downside is that ADRs that span multiple repositories need to pick one repo as home, or you need a dedicated documentation repo.

Wiki storage (Notion, Confluence, GitHub Wiki) is easier for non-engineers to access. It supports richer formatting and linking. Cross-cutting ADRs that affect multiple services have a natural home. The downside is drift: wiki pages do not go through code review, they are not versioned with the same rigor, and they become stale faster because updating them is not part of the normal development workflow.

My recommendation: store ADRs in the repo by default. Use a wiki only for decisions that genuinely span the entire organization and have no single repository home. For most teams, the in-repo approach produces better long-term results because the ADR is maintained by the same people who maintain the code, using the same tools.

Making teams actually write them

The hardest part of ADRs is not the format. It is getting engineers to write them. Every team that has tried ADRs and abandoned them failed at the same point: the process was too heavy, so people stopped doing it.

The fix is to make ADRs lightweight enough that writing one takes less time than the meeting where the decision was discussed. Five practical tactics:

  1. Template in the repo. Put an ADR template at /docs/adrs/TEMPLATE.md. Engineers should be able to copy it and fill it in within ten minutes. If it takes longer, the template has too many fields.
  2. Write it during the decision meeting. The person who facilitated the discussion writes the ADR immediately afterward, while the reasoning is fresh. Do not create a follow-up task. Follow-up tasks for documentation never get done.
  3. Include it in the PR. If a pull request introduces a significant architectural choice, the ADR is part of the PR. Reviewers can validate the reasoning alongside the implementation. This also means the ADR is reviewed by the same people who review the code.
  4. Keep the bar low. A three-paragraph ADR that captures the context, decision, and two consequences is infinitely more valuable than no ADR. Do not let the perfect be the enemy of the written.
  5. Reference ADRs in spec reviews. When reviewing a spec, ask: "Are there architectural decisions here that need an ADR?" Make it part of the spec checklist, not a separate process.

The goal is to reach a state where writing an ADR feels like writing a commit message for an architectural choice. Short, routine, and done in the moment.

Common mistakes

Teams that adopt ADRs tend to make the same mistakes in the first few months. Recognizing them early saves the practice from being abandoned.

Writing ADRs after the fact. An ADR written three months after the decision was made is not much better than no ADR. The reasoning has faded. The alternatives that were considered have been forgotten. The document becomes a rationalization of the current state rather than a genuine record of the decision process. Write ADRs when the decision is made, not when someone asks why.

Omitting rejected alternatives. The most valuable part of an ADR is the section that explains what was not chosen and why. "We chose PostgreSQL" is a fact that the code already tells you. "We rejected DynamoDB because reconciliation queries require multi-table joins that DynamoDB does not support efficiently" is knowledge that would otherwise be lost. If your ADR does not name at least one rejected alternative, it is incomplete.

Making them too long. An ADR is not a design document or a technical spec. It is a decision record. If your ADR is longer than one page, you are either documenting multiple decisions (split them) or including implementation details that belong in the spec. Keep it focused on the single decision and its rationale.

Never updating the status. When a decision is superseded by a new one, the old ADR should be marked as deprecated with a link to its replacement. ADRs with stale statuses erode trust in the entire collection. A simple "Superseded by ADR-042" in the status field is sufficient.

Treating them as approvals. An ADR records a decision. It is not a governance gate. Teams that require ADR approval before any technical work create a bureaucratic bottleneck that kills velocity. The ADR should be written and reviewed as part of the normal engineering workflow, not as a separate approval process.

ADRs in a spec-first workflow

In a spec-first approach, you write the spec before writing code. ADRs fit naturally into this workflow because the spec-writing process is exactly when architectural decisions get made. You are designing the system on paper, evaluating trade-offs, and choosing approaches. The decisions happen during spec writing. The ADR captures them.

The practical integration looks like this: when you write a technical spec, any section where you chose between alternatives gets a companion ADR. The spec says "the billing ledger will use PostgreSQL." The ADR says why. The spec references the ADR by number. The ADR links back to the spec. Both go through review together.

This also means the ADR is written at the point of maximum context. You have just finished evaluating the alternatives. You know why you rejected each one. You can articulate the consequences clearly. Three months later, that clarity will have faded. Capturing it now, while the reasoning is sharp, is the entire point.

Teams that adopt both specs and ADRs find that the combination answers nearly every question a future engineer will have about the system. The spec explains what was built and how. The ADR explains why. Together, they form a complete record that survives team turnover, organizational change, and the natural decay of institutional memory.

Keywords: architecture decision records · ADR template · technical documentation · spec-first development · software architecture decisions

Topic Path

This article belongs to the Spec-First Development track. Start with the hub, then use the checklist, template, or tool below on a real project.

Generate specs interactively
Fill a form, get a complete feature spec in Markdown — free, no signup.
Try the Spec Generator

Editorial note