4 min read

Architecture Decision Records That Teams Keep Using

A useful ADR captures the forcing context, chosen trade-off, and consequences at the moment of decision.

Listen to this article

Preparing audio…

Architecture

I consider an architecture decision record useful when a future engineer can recover the context, understand the trade-off, and tell whether new evidence should supersede it.

Architecture decision record lifecycle from proposal to acceptance, implementation, review trigger, and superseding record
Figure 19. Accepted ADRs remain immutable historical records; new evidence creates a linked superseding decision rather than rewriting the past.

The question an ADR must answer

Code shows what the system does now. It rarely preserves why one option was chosen, which constraints mattered, what was deliberately not solved, or what evidence would justify reversal. Those details disappear when a chat closes or a meeting ends.

Michael Nygard’s original “Documenting Architecture Decisions” proposed a deliberately small record: title, context, decision, status, and consequences. The format remains useful because it captures a decision at the moment the trade-off is understood, not months later as historical fiction.

An ADR is appropriate for a decision that is architecturally significant, costly to reverse, contested, or likely to surprise a future maintainer. It is not required for every library update or implementation detail. Teams should define their threshold and use examples to calibrate it.

A compact record with sharp fields

I start with a record that fits on one or two screens:

  1. ID, title, date, owner, status. Use a stable sequence or identifier and a verb phrase such as “Use an outbox for payment events.”
  2. Context. State the forces: scale, reliability, regulation, team capability, deadlines, existing constraints, and what is out of scope.
  3. Options considered. Present credible alternatives fairly, including “do nothing.” Link experiments or measurements.
  4. Decision and rationale. State the chosen option and the decisive trade-off. “Use Kafka” is not a rationale.
  5. Consequences. Record benefits, costs, risks, migration work, and operational obligations.
  6. Validation and review triggers. Define how the assumption will be tested and what evidence would prompt reconsideration.
  7. Links. Connect code, diagrams, incidents, benchmarks, issues, and related ADRs.

The AWS ADR process guidance similarly describes concise context, options, decision, consequences, ownership, status, review, and superseding accepted records rather than editing them silently. Treat the page as living guidance and capture the access/version context when using it as an organizational standard.

A worked example: synchronous call or outbox

Weak record:

We chose events because they scale better.

This cannot be challenged. It omits the transaction boundary, delivery expectations, operational cost, alternatives, and measurement.

Here is how I would make the synthetic record stronger. It says the service must commit an order and reliably notify downstream fulfilment without a distributed transaction. It compares a synchronous downstream call, database polling, change-data capture, and a transactional outbox. It chooses the outbox because the order row and outbound record can share one local transaction, while acknowledging duplicate delivery, ordering, relay operations, and consumer idempotency. It links a failure test and states review triggers: database throughput below a threshold, relay lag above a service objective, or adoption of a platform capability that provides equivalent guarantees.

The record does not prove the design works. Tests, telemetry, and operational documentation provide current evidence. The ADR explains why this design was chosen under stated conditions.

Put ADRs in the path of work

Store ADRs close to the code or architecture repository they govern. Use a predictable directory, searchable index, and lightweight template. A pull request works well because reviewers can comment alongside the proposed implementation and the accepted record becomes versioned.

Suggested states are proposed, accepted, rejected, deprecated, and superseded. Ownership and decision date prevent an orphaned proposal from appearing authoritative. When a decision changes, create a new ADR that links supersedes and update the old record to point to it without erasing its original context.

The AWS introduction to using ADRs to streamline decisions emphasizes alignment, decision history, reduced repeated debate, and handover. Those benefits depend on discoverability and adoption; creating files alone produces no organizational memory.

Integrate simple checks: unique IDs, required fields, valid status links, and an index. More important, include an ADR link in significant design pull requests and incident reviews. If a production event invalidates an assumption, open the review trigger rather than leaving the record as dead documentation.

Review without approval theatre

Review should improve the decision while it is reversible. Ask:

  • Is the problem and scope clear?
  • Are alternatives represented honestly?
  • Which evidence supports the decisive assumption?
  • Who carries each consequence?
  • How will implementation validate the choice?
  • What new fact would cause reconsideration?

Avoid committees for every record. Match reviewers to impact: security for a trust boundary, data engineering for consistency, operations for on-call consequences, and product for user-facing trade-offs. Time-box discussion and name the decision owner. Consensus is useful but not always possible; accountability must remain clear.

Failure patterns that make ADRs decay

Decision archaeology. Writing the ADR after implementation turns it into justification. Draft it with the proposal.

Template inflation. A dozen mandatory sections encourages vague filler. Keep the core short and link supporting evidence.

Technology inventory. “We use PostgreSQL” is not a decision unless the context, alternatives, and consequences are present.

Mutable history. Rewriting an accepted ADR hides why earlier implementation exists. Supersede it explicitly.

No review trigger. A record based on traffic, cost, regulation, or team assumptions needs a signal that can invalidate them.

Disconnected truth. An ADR that cannot be reached from code, service catalogues, or architecture views will not be found when needed.

The smallest useful discipline

Start with one repository, a seven-field template, a review state, and supersession links. Apply it only to meaningful choices. Revisit records during incidents, migrations, and major design changes.

My design rule is not comprehensive documentation. I want to preserve the reasoning that code cannot express: what was known, which compromise was chosen, who accepted the consequences, and which evidence should make the team decide again.

References

Engineering discussion

What decision would you make?

Add a question, a field note, or a respectful counterpoint. Comments are for signed-in members so the discussion stays useful and professional.