GuideCustom Software Development
Architecture decision records: how to write, store and keep them useful
An architecture decision record captures one significant design choice: the situation, the options weighed, what was chosen and what follows from it. Kept in the repository beside the code, a set of them explains why a system looks the way it does long after its authors have moved on. This guide covers the template, which decisions deserve a record, how to supersede rather than edit, and three worked examples.
On this page
- The problem ADRs solve: decisions outliving their authors
- Which choices deserve a record, and which do not
- The fields of a record and what belongs in each
- Worked example: a retrieval store for an agent system
- Worked example: managed queue or self-run Kafka
- Worked example: native HTS token or smart-contract token
- Numbering, review and superseding in the repository
- Records in sprint reviews and at handover
- Mistakes that turn decision records into shelfware
- Questions and answers
- Sources
Which choices deserve a record, and which do not
A useful test: would a capable engineer joining next year be tempted to undo this, and would undoing it be expensive?
- If
The choice is costly to reverse: a database, message backbone, ledger, cloud provider or language for a core service.
ThenWrite a record.
Reversal means migration, and the record shows what a migration would give up.
- If
The choice fixes a contract other teams rely on, such as a schema evolution policy, API versioning rule or authentication method.
ThenWrite a record and link it from the contract's documentation.
Other teams need to know the rule and its reason before they work around it.
- If
A non-functional target forces the design, for example a recovery objective that rules out a single region.
ThenWrite a record that names the target.
If the target changes, readers can see which decisions are open again.
- If
You are swapping one utility library for another inside a single module.
ThenSkip it; the pull request description is enough.
A record set full of trivia stops being read.
The fields of a record and what belongs in each
This template adds an explicit options field to Nygard's five sections, because rejected alternatives are what later readers most often need.
- Title
- A sequential identifier such as ADR-0012 and a short phrase naming the decision: 'Use managed Kafka for domain events', not 'Messaging'.
- Status
- Proposed, accepted, deprecated or superseded. A superseded record links forward to its replacement, which links back.
- Context
- The forces at play, written as checkable facts: requirements, constraints, targets, team skills, deadlines and costs.
- Options considered
- Each realistic alternative, including doing nothing, with its main advantage and drawback in a sentence or two.
- Decision
- The choice in the active voice ('We will…') and its scope, so readers know where it does not apply.
- Consequences
- What becomes easier, what becomes harder, the risks accepted and the conditions that should trigger a revisit.
Worked example: a retrieval store for an agent system
Worked example: managed queue or self-run Kafka
Worked example: native HTS token or smart-contract token
Numbering, review and superseding in the repository
Propose through a pull request
Add a file under a folder such as docs/adr with the next identifier and status proposed, so the decision is reviewed in the same tool as code.
Review with the people affected
Invite the engineers who will build on it and the owners of any system it touches. Their comments become part of the record's history.
Accept on merge
Set the status to accepted when the pull request merges. From then on the text is frozen except for status and links.
Supersede instead of editing
When circumstances change, write a new record that cites the old one, and mark the old one superseded with a forward link.
Deprecate what no longer applies
If a decision stops mattering, for example because a component was retired, mark it deprecated with a one-line reason rather than deleting it.
Generate an index
A generated list of identifiers, titles and statuses at the top of the folder lets a newcomer scan every decision quickly.
Records in sprint reviews and at handover
ColdAI's two-week sprints each end in a demonstration of deployable software,2 and that is a natural place to walk through any record accepted during the sprint, so the product owner sees trade-offs as they are made. Sprint planning is the moment to ask whether a proposed decision can wait until more is known.
At handover, the record set is among the first things an incoming team should read. Together with the system design document it answers most 'why is it like this?' questions without a meeting, which is why the software handover checklist treats a current set of records as a condition of acceptance.
Mistakes that turn decision records into shelfware
Writing records in bulk after the fact
Early signalA batch of records appears just before an audit or a handover.
MitigationWrite each record when the decision is made; reconstruct old ones only where they still constrain the system, and label them reconstructed.
Leaving out rejected options
Early signalRecords state a choice with no alternatives.
MitigationRequire at least two genuine options, one of which may be doing nothing, before review.
Essays instead of records
Early signalRecords run to many pages and go unread.
MitigationKeep the record to what a reader needs and link to longer analysis.
Editing accepted records
Early signalA record's history shows its decision text changing.
MitigationFreeze accepted text and supersede it with a new record.
Questions and answers
Where should architecture decision records be stored?
In the repository of the system they describe, usually a docs/adr folder, as plain Markdown. That keeps them versioned with the code, reviewable through pull requests and visible to anyone who can read the code. Decisions spanning several systems can sit in a shared architecture repository, linked from each affected system. Wikis tend to drift from the code and lose the review history.
How long should an architecture decision record be?
Most fit on a page or two. Context and consequences deserve the most words; the decision itself is often a single sentence. If a record grows much longer, the extra material is probably analysis, such as a benchmark write-up or an options paper, that belongs in a linked document. Brevity is what gets a whole record set read.
Who approves an architecture decision record?
Whoever owns the architecture for the affected scope, typically a technical lead or architecture group, after review by the engineers who will live with it. Write the approval rule down, often in the first record of the set. Decisions with cost, security or contractual consequences may also need the product owner or a security lead to agree before the status becomes accepted.
How is an ADR different from a system design document?
A design document describes the system as it stands: components, data flows, interfaces and targets. A decision record captures one choice and why it was taken. They work as a pair. When the design changes, the document is updated in place, while records are superseded rather than rewritten, so the history of how the system reached its current shape stays intact.
Sources
- Documenting Architecture Decisions — Michael Nygard, Cognitect · checked 10 October 2026
- Custom Software Development: delivery stages and handover deliverables — ColdAI