szpak szpak

Documenting Key Choices With Architecture Decision Records

ADRs capture the reasoning behind important technical decisions so teams do not have to rediscover it the hard way.


Someone joins the team, opens the codebase, and asks a perfectly reasonable question.

Why does the shopping cart use Redis when everything else uses SQL?

The answer exists. At least it did. It lived in a meeting, three Slack threads, and the head of the engineer who left eight months ago.

That is usually the moment a team realizes it does not have an architecture problem. It has a memory problem.

Architecture Decision Records solve exactly that.

What An ADR Is For

An ADR is a short record of an important technical decision and the reasoning behind it.

Not just the outcome. The reasoning.

That distinction matters. Teams are usually good at remembering what exists. They are much worse at remembering why it exists. Without that why, later cleanup efforts can accidentally remove the very thing that kept the system stable.

Take that shopping cart example. Maybe Redis was introduced because the feature had become a bottleneck. Maybe the team needed to reduce pressure on external services and cache data aggressively to keep latency under control. If that story is not written down, somebody will eventually “standardize” the feature back to SQL and quietly reintroduce the problem.

That kind of cleanup looks responsible right up until production disagrees.

When To Write One

Not every technical choice deserves an ADR.

If your team always uses PostgreSQL, or always uses Python, or has a naming convention everybody already understands, writing a formal record for it may be ceremony without value.

An ADR becomes useful when a decision has one or more of these traits:

  • it was debated
  • it has meaningful trade-offs
  • it is likely to be questioned later
  • it changes how the system should evolve
  • getting it wrong later would be expensive

That usually means architecture, infrastructure, integration, deployment, security, and data decisions. The kind people revisit six months later with great confidence and incomplete context.

Where To Keep ADRs

An ADR is usually just a small Markdown file.

It does not have to be. A wiki, ticketing system, or internal portal can work too. But plain files stored in version control have one big advantage: they evolve with the system. You can review them, diff them, and keep them close to the code they explain.

I prefer storing them in the repository for exactly that reason. They stay visible, searchable, and easy to reference in pull requests or discussions.

There is another useful side effect. When records live with the code, other teams can inspect the reasoning too. That is often enough to catch bad assumptions before they turn into expensive “alignment meetings.”

Do Not Rewrite The Past

This part matters.

An ADR is a record, not a living marketing document. If the decision changes, create a new record that supersedes the old one instead of overwriting history.

Why? Because the old decision was still real. It was made under a particular set of constraints, and those constraints are part of the story. Once you erase them, you also erase the context future readers need in order to understand how the system got here.

Teams do enough accidental revisionism already. No need to help it.

A Simple Structure That Works

There are a few widely used ADR formats. One of the better known ones comes from Michael Nygard, and it is popular for a reason. It is short, practical, and hard to misunderstand.

The core sections are straightforward.

Status

Use a status that tells readers whether the record is current, pending, or obsolete.

  • proposed
  • accepted
  • rejected
  • deprecated
  • superseded

Title

Keep the title specific and decision-shaped.

  • Choose RabbitMQ over Kafka
  • Use Redis for Shopping Cart Reads
  • Store Metrics in a Time-Series Database

The title should tell readers what was decided without making them read three paragraphs first.

Context

Explain the problem, constraints, and forces around the decision.

This is where you document the messy part: performance pressure, delivery deadlines, team knowledge, operational limits, compliance requirements, migration risks, whatever actually influenced the choice.

Decision

Say what you chose.

Not in vague language. Not in corporate fog. State the decision and, if needed, the practical implementation path.

Consequences

This is the section teams skip too lightly, which is unfortunate, because it is often the most useful one.

What gets easier now? What gets harder? What operational cost did you accept? Does this create new scalability limits? Does it reduce risk in one place while increasing it somewhere else?

That is the real trade-off surface. Write it down.

Naming And Storage Conventions

If you keep ADRs in the repository, simple conventions help.

  • store them in an adr directory near the root
  • use kebab-case file names
  • name files as decisions, usually with an imperative verb

Examples:

  • choose-message-broker.md
  • use-redis-for-cart-reads.md
  • introduce-outbox-pattern.md

Nothing exotic is required here. The goal is easy lookup, not creativity.

Final Thought

Good teams do not just make decisions. They leave behind enough reasoning for the next team member to understand them without archaeology.

That is what an ADR really buys you.

Not documentation theater. Shared memory with receipts.