Skip to main content

Architectural Decision Records (ADRs)

Every codebase is shaped by decisions that nobody wrote down. ADRs fix that by documenting the why behind architectural choices.

Why did we choose PostgreSQL over MySQL? Why is this service in Go instead of Java? When the people who made those decisions leave, the context leaves with them. ADRs are short, structured documents that preserve that context for everyone who comes after.

What is an ADR?

An Architectural Decision Record is a short document that captures a single architectural decision. Originally proposed by Michael Nygard, an ADR is typically one page or less and includes: a title, the date it was written, the current status (proposed, accepted, deprecated, or superseded), the context that motivated the decision, the decision itself, and the consequences -- both positive and negative.

ADRs are not design documents. They do not need to be comprehensive or cover every detail. They need to capture the why -- the reasoning, the tradeoffs considered, and the alternatives rejected. The goal is that someone reading the ADR six months or six years later can understand not just what was decided, but why it was the right call at the time.

The power of ADRs is in their simplicity. A decision that takes an hour to make should take fifteen minutes to document. If your ADR process takes longer than that, your template is too complex or you are trying to document too much in a single record.

ADR Template

This is the classic Nygard-style ADR template. Simple, effective, and battle-tested across thousands of teams. Copy it into your repository and start using it today.

# ADR-{NUMBER}: {TITLE}

**Date:** YYYY-MM-DD   |   **Status:** Proposed | Accepted | Deprecated | Superseded

## Context

What is the issue that we are seeing that is motivating this decision or change? Describe the forces at play including technical, political, social, and project constraints.

## Decision

What is the change that we are proposing and/or doing? State the decision in full sentences, with active voice. "We will use PostgreSQL for all new services."

## Consequences

What becomes easier or more difficult to do because of this change? List both positive and negative consequences. Be honest about the tradeoffs.

Tip: Store ADRs as numbered markdown files in your repository (e.g., docs/decisions/0001-use-postgresql.md). This keeps decisions versioned alongside the code they describe and makes them discoverable through code search.

When to Write ADRs

Not every decision needs an ADR. Focus on decisions that are hard to reverse, affect multiple teams, or will confuse future developers if left unexplained.

Technology Choices

Database selection, programming language choice, framework adoption, cloud provider selection, and third-party service decisions. These are expensive to reverse and affect the entire team's workflow and hiring strategy.

Architecture Patterns

Microservices vs monolith, event-driven vs request-response, caching strategy, and service boundaries. These decisions shape how your system grows and determine which future changes are easy and which are painful.

API Design Decisions

Versioning strategy, authentication method, error format, and pagination approach. API decisions are especially important to document because they create contracts with external consumers that are difficult to change.

Data Decisions

Schema design, data partitioning strategy, backup approach, retention policies, and data ownership boundaries. Data decisions are the hardest to reverse because they affect every query, every report, and every downstream system.

Build & Deploy

CI/CD tool choice, deployment strategy (blue-green, canary, rolling), testing approach (unit vs integration vs E2E balance), and branching model. These decisions affect every developer's daily workflow and deployment confidence.

Security & Compliance

Authentication mechanisms, authorization models, encryption standards, audit logging, and data classification rules. Security decisions are often made once and assumed forever -- documenting the reasoning helps teams evaluate when to revisit them.

ADR Tooling

You do not need any tooling to start writing ADRs -- a folder of markdown files works. But tools can reduce friction and help your team adopt the practice more consistently.

adr-tools

A command-line tool for managing ADRs as numbered markdown files in your repository. Run "adr new Use PostgreSQL for user data" and it creates a new file with the right number, date, and template. Simple, Unix-philosophy, and widely adopted. Zero overhead once installed.

Best for: Teams that prefer CLI tools and want minimal overhead

Log4brains

Web-based ADR management with full-text search, visualization, and a static site generator. Browse your decisions in a web interface, see relationships between ADRs, and search across all records. More features than adr-tools but more setup required.

Best for: Teams that want a browsable knowledge base of decisions

Structurizr

Combines architecture diagrams (C4 model) with decision records. See your system structure and the decisions that shaped it in a single tool. Particularly good for visual teams and for onboarding new team members who need to understand both the system and the reasoning behind it.

Best for: Teams that want diagrams and decisions in one place

Repository-Based (No Tooling)

Just a /docs/decisions/ folder with numbered markdown files. Zero tooling overhead. Copy the template, fill it in, commit it. This approach works surprisingly well for small-to-medium teams. You lose search and visualization but gain simplicity. Start here and add tooling only when the folder gets too large to browse.

Best for: Teams that want zero setup cost and maximum simplicity

Common ADR Mistakes

ADRs are simple in concept but easy to get wrong in practice. These mistakes reduce their value and discourage adoption.

Writing Design Documents

ADRs are not design docs. If your ADR includes class diagrams, API specifications, or implementation details, you are writing the wrong document. ADRs capture the decision and its context -- not the full design. Link to design docs from the ADR if needed.

Writing Them After the Fact

Retroactive ADRs lose the context they are meant to preserve. If you write an ADR three months after the decision, you have already forgotten the alternatives you considered and the tradeoffs that influenced your choice. Write ADRs while the decision is fresh.

Hiding Them in Confluence

ADRs stored in a wiki die quietly. Nobody searches the wiki before writing code. Store ADRs in the code repository, in a /docs/decisions/ folder, so they are versioned alongside the code and discoverable through code search and pull request reviews.

Editing Accepted ADRs

Modifying an accepted ADR destroys the historical record. If a decision changes, create a new ADR that supersedes the old one. The old ADR should be marked as superseded with a link to its replacement -- never deleted or modified.

Skipping the Context

"We chose React" is not an ADR. Why did you choose React? What were the alternatives? What constraints influenced the decision? The context section is the most valuable part of an ADR -- it is what future developers need to evaluate whether the decision still makes sense.

Only Listing Positives

Every decision has tradeoffs. If your consequences section only lists benefits, you are not being honest about the decision. Future developers need to know what became harder, not just what became easier. Honest tradeoff documentation builds trust and helps teams make informed revisitation decisions.

Detecting ADR Violations

An ADR is only useful if the team follows it. These enforcement mechanisms catch violations before they ship to production.

Architecture Fitness Functions

Automated tests that verify your system conforms to architectural decisions. If your ADR says "all services must communicate through the message bus," a fitness function can detect direct HTTP calls between services and fail the build. These run in CI alongside your unit tests and catch drift before it reaches production.

ArchUnit Tests

ArchUnit (Java/Kotlin), NetArchTest (.NET), and similar tools let you write unit tests for your architecture. Test that controllers do not access repositories directly, that certain packages only depend on specific other packages, or that classes in the domain layer have no framework imports. These tests enforce ADR decisions at the code level.

Dependency Rules in CI

Use dependency analysis tools in your CI pipeline to enforce module boundaries. If an ADR says "the billing module must not depend on the user interface module," your CI pipeline should catch any import that crosses that boundary. Tools like Dependency Cruiser (JavaScript), ArchUnit, or custom scripts can enforce these rules automatically.

Code Review Checklists

Add a checklist to your pull request template: "Does this change conform to existing ADRs?" and "Does this change require a new ADR?" This is the lowest-effort enforcement mechanism. It relies on humans rather than automation, but it raises awareness and catches violations that automated tools might miss -- like subtle architectural drift that is technically compliant but violates the spirit of a decision.

Regular Architecture Reviews

Schedule quarterly architecture reviews where the team walks through active ADRs and evaluates: Are we still following this? Should we still be following this? Has the context changed enough to warrant a new decision? This is where you catch slow architectural drift that accumulates through dozens of small, individually-reasonable changes.

Related Resources

Frequently Asked Questions

One page or less. If your ADR is longer than a page, you are either documenting multiple decisions (split them) or including too much background (link to external docs instead). The goal is to capture the decision and its context quickly, not to write a comprehensive design document.

Anyone who makes or proposes an architectural decision. In practice, this is usually senior engineers, tech leads, and architects. Make writing ADRs a natural part of the decision-making process, not a separate documentation task. If a decision comes up in a meeting, someone should own writing the ADR.

Make it frictionless: provide templates, use CLI tools (adr-tools), store ADRs in the code repository alongside the code they describe. Include ADR creation in your definition of done for architecture changes. Review ADRs in pull requests. If writing an ADR takes more than 15 minutes, your template is too complex.

Never modify an accepted ADR. If a decision changes, create a new ADR that supersedes the old one and link them. This preserves the historical record of why decisions were made and changed. The sequence of decisions tells a valuable story about how your architecture evolved.

An ADR that is consistently violated indicates one of two things: the decision was wrong and should be superseded, or the team lacks enforcement mechanisms. Use architecture fitness functions and code review checklists to detect violations. If a decision is regularly bypassed, revisit it rather than ignoring the violations.

ADRs prevent debt by making the rationale for decisions explicit. When new team members understand why decisions were made, they are less likely to accidentally undermine them. When circumstances change, teams can evaluate whether the original reasoning still applies before making changes. They replace tribal knowledge with documented knowledge.

Start Documenting Your Decisions Today

The best time to start writing ADRs was when the first architectural decision was made. The second best time is right now. Create a docs/decisions/ folder and write your first ADR.