Architecture decision records
Record why an architecture choice was made, which assumptions could change it, and when to review it without rewriting the history of the decision.
An architecture decision record explains one significant choice, the context that made it reasonable and the consequences the team accepted. Keep the original reasoning when the choice changes: mark the old record as superseded and link to its replacement.
You leave a note saying why the workshop uses a small delivery van: everything currently fits through a narrow entrance. When larger deliveries arrive, the note helps the next person reconsider the choice instead of guessing why you made it.
Use the ADR template#
Download the blank ADR template (Markdown). Replace the bracketed prompts and keep the status as proposed until the decision is actually accepted.
View and copy the complete template
# ADR [number]: [one decision in a short title]
Keep one decision per file. Replace the bracketed prompts with what is actually known; mark unknowns rather than inventing evidence. Save the record alongside the code, for example as docs/decisions/0001-short-title.md.
## Decision
We will [specific action and scope].
## Context
Date of the decision: [YYYY-MM-DD]
Decision owner and reviewers: [people responsible for the choice]
[Describe the constraint, workload, existing system and deadline that matter now. Separate measured facts, assumptions and unknowns. Link to the issue, design discussion or reproducible evidence.]
## Alternatives rejected
- [Alternative A]: [Why it does not satisfy the relevant constraints; what it would do better.]
- [Alternative B or the current approach]: [Why it was not chosen; when it would become preferable.]
## Consequences accepted
[State the useful effect and the cost we deliberately accept. Name the changed failure mode, operational responsibility, dependency or reversal cost. Describe what observation would justify revisiting the choice.]
## Status
Proposed | Accepted | Superseded — choose one.
Supersedes: [previous record, when applicable]
Superseded by: [replacement record, when applicable]
When the decision changes, create a new record. Mark this record as superseded and link to the replacement; do not rewrite its historical context to match the new system.
---
This template follows the five-field structure in Software Made Clear's architecture decision records guide: https://softwaremadeclear.com/architecture-decision-records/
It is a blank working template, not a claim that any decision has already been reviewed or approved. Download a filled-in ADR example (Markdown). The example is fictional, not a production benchmark or an approved decision. It distinguishes constraints, assumptions and questions still to test.
A new engineer finds that reports run inside the main application. A separate worker looks like the obvious alternative. Was it considered? Was there a constraint that no longer applies? The code shows what the team built, but it cannot answer those questions on its own. A short record can preserve the missing reasoning.
What the file has to contain#
The template above makes five things explicit. Each should help someone understand the choice, not merely show that a form was completed.
| Field | What the reader needs |
|---|---|
| Decision | What was chosen, in a direct sentence: “Reports run inside the application,” rather than “Reporting options were discussed.” |
| Context | The constraints and facts that mattered at the time. Label assumptions separately from things the team actually observed. |
| Alternatives rejected | Which realistic options were considered, what each would have bought and why the chosen option suited the constraints better. |
| Consequences accepted | The disadvantages and obligations as well as the benefits. Who now needs to monitor, maintain or work around this choice? |
| Status | Whether the choice is proposed, accepted or superseded, with a link when another record replaces it. |
This is the site’s adaptation, not a verbatim copy of the original format. Michael Nygard’s proposal uses title, context, decision, status and consequences. Our template names rejected alternatives explicitly. The purpose is the same: preserve enough reasoning to avoid both blindly accepting and blindly reversing a past choice.
Assumptions and review triggers#
A reason can be sensible and temporary. Recording that distinction makes the ADR useful when the system changes. Consider this illustrative reporting decision; the limits below are invented for the example, not recommended thresholds or production measurements.
| Record | What the team writes |
|---|---|
| Current constraints | Reports are limited to 10,000 rows and only one report may run at a time. |
| Decision and alternative | Keep report generation in the application for now. A separate worker would isolate the work but introduce another deployment and a job hand-off. |
| Uncertain assumption | The permitted report workload can share the application’s resources without an unacceptable effect on interactive requests. This needs testing; the row limit alone does not establish it. |
| Review trigger | Before raising the row limit or permitting concurrent reports, the reporting team reviews this decision. Evidence of unacceptable interference also triggers a review. |
| Evidence to bring | The proposed workload, measurements of resource use and request latency, and the operating cost and failure cases of the alternatives. |
Now a new requirement asks for 100,000 rows. The trigger has fired, but “add a worker” is not yet the conclusion. Streaming results inside the application, moving work elsewhere and changing the user-facing behaviour remain different options. The review needs evidence about those options under the new requirement.
Write what would make the current choice unattractive, not just what would confirm it. For this example: “If report generation causes unacceptable delay for interactive requests under the agreed workload, revisit the shared-process choice.” The team must define an acceptable delay and measure it; calling a design simple does not settle that question.
A review trigger is our suggested extension, not a mandatory ADR field. It can be a short sentence in the context or consequences rather than a new process. Give it an owner and a way to be noticed. An unobserved threshold in a document is not monitoring, and a trigger that nobody owns is only a reminder.
After reviewing, the team may retain the decision and append a dated review note. If it changes the decision, it writes a new ADR and links it to the old one. Either way, it keeps the original assumptions distinguishable from the information learned later. A good result alone does not prove that the original reasoning was sound; a disappointing result does not tell us which assumption failed.
Why they die#
Three habits make a directory of records less useful. The first is writing from memory after the implementation, when the rejected options are harder to recover. The second is writing for an unspecified audience: long background sections hide the actual choice. The third is recording every minor decision, so the important ones become difficult to find.
Reserve ADRs for choices whose context matters to future changes. Nygard’s examples of significant decisions include structure, dependencies, interfaces and non-functional characteristics. The cost of reversing a choice is a useful consideration, not a fixed time threshold. A small change to an externally used interface may deserve a record even if the code took an afternoon.
The retry promise made by an API is one example: callers may depend on it long after the implementation changes. The boundary between code and deployment configuration is another. An ADR records why the team chose the boundary; it does not replace the documentation of the current contract.
The record that got rewritten#
Suppose someone edits the reporting ADR so that it now says the team always expected 100,000-row reports. The page looks up to date, but it no longer explains the original decision. A future reader cannot tell whether the team knowingly accepted that workload or discovered it later.
Keep that history intact. A spelling correction, a dated clarification and a status change are not the same as replacing the old reasoning. When the architecture changes, mark the earlier decision as superseded and explain the new choice in a linked record. Do not make the earlier team appear to have known what only became clear afterwards.
Questions that are still open belong in a design discussion people can challenge. Once a choice is accepted, its ADR records the result and consequences. Keeping those jobs separate lets the current system evolve without erasing the path that led to it.
IF YOU REMEMBER ONE THING
Record why the choice made sense, what remains uncertain and what would prompt another look. A later review should add knowledge, not rewrite what the team knew at the time.
Questions people also ask
6 QUESTIONSWhere should ADRs live?
Keeping them in the repository makes it possible to review a decision alongside the change it governs. Link the record from relevant documentation or code so that the next person can find it. A directory alone does not make decisions discoverable.
What happens when a decision changes?
Write a replacement, link both records and mark the old one as superseded. Preserve what was believed at the time. Correcting a typo or adding a dated status note is different from rewriting the original context to match today's system.
How long should an ADR be?
Long enough to explain one significant choice and its consequences, but small enough to read during a review. Nygard's original proposal suggests one or two pages. A large design may need several decisions rather than one record covering everything.
Do ADRs replace design documents?
No. A design document explores a proposed system and its trade-offs. An ADR records a specific decision. A runbook explains how to operate the result. The documents can link to each other without repeating all the same material.
Who should write the ADR?
The people making the decision should record its context while they can still explain the actual alternatives and constraints. Assign a reviewer or owning team when the decision needs later reassessment.
Does a review trigger automatically reverse the decision?
No. It means that an assumption deserves another look. The review may keep the decision, revise a limit or choose a replacement. A trigger is an instruction to reconsider, not an automatic migration rule.