The problem: nobody remembers why

Eighteen months after launch, a new engineer asks why the order service talks to the warehouse through a message broker while every other integration uses REST. Two people who knew the answer have left, the chat history is gone, and the wiki page says only "we use Kafka for async". The new engineer proposes replacing it with REST calls. Someone eventually remembers that the warehouse system goes offline every night for maintenance, and that was the reason. The team lost a week rediscovering a constraint that took ten minutes to write down originally.

An Architecture Decision Record (ADR) is a short document that captures one significant decision: the situation, the options considered, the choice and its consequences. It is a log, not a specification. It answers "why is it like this?" for the people who inherit the system, including your future self.

What deserves an ADR

Write one when a decision is expensive to reverse, affects several teams or sets a precedent. Typical examples:

  • choosing a datastore, a messaging technology or an authentication approach
  • splitting or merging services
  • adopting a framework or library that will spread through the codebase
  • defining a cross-cutting convention such as an error format or an API versioning scheme
  • deliberately accepting a known risk or a shortcut

Do not write an ADR for renaming a method or choosing a formatter. If the decision is easy to change in a single Pull Request, a code comment is enough.

A minimal template

Keep the template small enough that people will fill it in. The widely used shape has four parts plus metadata: context, options, decision and consequences.

# ADR-0007: Use a message broker between Orders and Warehouse

Status: Accepted
Date: 2026-03-12
Deciders: Orders team, Warehouse team, architect

## Context
Warehouse management is unavailable every night from 01:00 to 03:00
for maintenance. Orders must be accepted at any time. Today an
order placed during the window fails with a timeout. We expect
order volume to grow, and the warehouse team cannot change its
maintenance schedule this year.

## Options considered
1. Synchronous REST call with retries in Orders.
2. Orders writes an event; Warehouse consumes it when available.
3. Nightly batch export.

## Decision
We use option 2. Orders publishes OrderPlaced through a transactional
outbox; Warehouse consumes it with an idempotent handler.

## Consequences
+ Orders accepts orders during warehouse downtime.
+ Warehouse can be scaled and paused independently.
- Stock reservation becomes eventually consistent; the UI shows
  "confirmed" only after a ReservationCreated event.
- We now operate a broker and must monitor consumer lag.
- Duplicate delivery is possible; handlers must be idempotent.

## Revisit when
The warehouse supports 24/7 availability, or order volume stays low
enough that the broker is not worth its operational cost.

The most valuable parts are context (the forces at play, written so that a stranger understands them) and consequences (including the negative ones). If the consequences section lists only benefits, the record is advertising, not engineering.

Status lifecycle

An ADR is immutable once accepted, in the sense that you do not rewrite history. Its status changes instead:

  1. Proposed: under discussion, usually in a Pull Request.
  2. Accepted: agreed and in effect.
  3. Deprecated: no longer relevant, for example because the feature was removed.
  4. Superseded by ADR-00xx: replaced by a later decision, with a link in both directions.

When circumstances change, write a new ADR that supersedes the old one. The old record still explains why the system looks the way it does today, and the chain of records shows how thinking evolved.

A weak ADR versus a good one

A weak record looks like this:

# ADR-0012: Use PostgreSQL
Status: Accepted
We decided to use PostgreSQL because it is reliable and popular.

It has no context, no alternatives and no consequences. Nobody can tell what it was compared against, what the data looked like or when to reconsider. A better version states the workload (relational data with transactions across orders and payments), the alternatives that were truly considered, what the team already operates, the cost of the choice (for example, horizontal write scaling is harder) and a clear trigger for revisiting it.

Another weakness is the retrospective ADR written to justify a decision made months ago. Writing late is better than not writing, but label it honestly and capture the real constraints at the time, not a rationalization.

A short workflow

A simple flow keeps the practice alive without ceremony. Someone proposes a change that meets the "expensive to reverse" bar and opens a draft Pull Request with the ADR in Proposed status. Reviewers comment on the context and options, not on wording. When the group agrees, the status changes to Accepted and the Pull Request is merged, ideally together with the first implementation work. Months later, a newcomer reads the record, the monitoring tied to its consequences, and the revisit condition, and can decide with evidence whether it still holds.

Where to store them

Put ADRs in the repository they affect, for instance in a docs/adr/ folder with files named 0007-message-broker-between-orders-and-warehouse.md. Reasons:

  • they change through Pull Requests, so discussion and approval are visible
  • they version with the code they describe
  • they are found by anyone who clones the repository
  • a decision that spans several repositories can live in a dedicated architecture repository, referenced from the others

Number records sequentially and never reuse numbers. A short index file listing title and status helps navigation.

Signs of a good ADR

A stranger reading a good record a year later can answer four questions: what problem existed at the time, what else could have been chosen, why this option won and what it cost. The language is plain and concrete: instead of empty words like "good", "fast" or "modern", it states measurable constraints, such as "the maintenance window is two hours". The names of the deciders are recorded so the reader knows whom to ask. The record is written not to defend the decision but to make it easier to revisit.

ADRs and other documents

An ADR does not replace a design document, a runbook or a technical specification. A design document explains how the solution works, a runbook describes operations, and an ADR answers only the question "why was this path chosen". When the three documents link to each other, each stays short and nobody has to update the same information in three places.

Common mistakes

  1. Writing after the fact only. The discussion is where the real options live. Start the ADR as a draft Pull Request while the choice is still open.
  2. Hiding the alternatives. Listing only the winner makes the decision look obvious and invites the same debate later.
  3. No consequences. Every decision has costs; naming them builds trust and sets up monitoring and mitigation.
  4. Too long. One to two pages is enough. Link to detailed analysis instead of embedding it.
  5. Editing accepted records. Fix typos, but supersede decisions rather than rewriting them.
  6. Treating the ADR as approval theatre. The goal is shared understanding, not a signature.

Trade-offs

ADRs cost time, and a team that writes one for every small choice will stop writing them altogether. Be selective. They also do not replace diagrams: pair them with C4 diagrams so readers see both the shape of the system and the reasoning behind it. In very small, short-lived projects, a README section named "Decisions" may be sufficient.

Checklist

  • Does the title state the decision, not just the topic?
  • Does the context explain forces and constraints to a newcomer?
  • Are at least two real options listed with reasons for rejection?
  • Are negative consequences and risks named?
  • Is there a status, a date and a list of deciders?
  • Is there a condition under which the decision should be revisited?
  • Is the record in the repository and linked from related diagrams?

Where to go next

See how decisions fit into the wider job in the solution architect role, look at the system-level view in the C4 model guide, or take the skills assessment to see where your architecture practice stands.