Six months after a decision, nobody remembers why you chose PostgreSQL over MongoDB, or why the authentication service is separate, or why you’re not using GraphQL. New team members make the same arguments that were already debated. Old team members make the same counter-arguments. You relitigate the past instead of building the future.

Architecture Decision Records (ADRs) are a lightweight solution: a short text file per significant decision that captures what was decided and why. That’s it.

What Is an ADR?

An ADR is a short document (half a page to two pages) that records an architectural decision. The format matters less than the habit. A minimal ADR has four fields:

  • Title: a short, present-tense title
  • Status: proposed / accepted / deprecated / superseded
  • Context: why is this decision needed? What forces are at play?
  • Decision: what did we decide?
  • Consequences: what are the trade-offs? What becomes easier or harder?

A Simple Template

# ADR-0012: Use PostgreSQL as the primary database

## Status
Accepted — 2026-01-15

## Context
We need a primary database for user data and orders. Our data is relational,
we have existing team expertise in SQL, and we need strong ACID guarantees for
financial transactions. We evaluated PostgreSQL, MySQL, and MongoDB.

## Decision
We will use PostgreSQL as our primary database.

MongoDB was rejected because our data is relational and we need joins and
transactions. MySQL was considered but PostgreSQL's JSON support, window
functions, and active community made it the stronger choice.

## Consequences
- Strong ACID guarantees for all critical data ✅
- Excellent tooling (pgAdmin, TypeORM, Prisma) ✅
- Team already knows SQL ✅
- Horizontal write scaling requires additional tooling (read replicas are easy,
  write sharding is not) ⚠️
- JSON document storage is possible but not the primary use case ℹ️

Where to Store ADRs

The best place is next to your code, in version control:

docs/
  decisions/
    0001-use-typescript.md
    0002-use-postgres.md
    0003-separate-auth-service.md
    0012-adopt-event-driven-architecture.md

Storing ADRs with the code means:

  • They’re versioned alongside the code they describe
  • Pull requests can include an ADR when introducing a big change
  • They’re searchable with grep or your editor

Don’t use Confluence or Notion — they become stale and unsearchable.

The adr-tools CLI

There’s a small CLI tool that scaffolds ADRs:

# Install
brew install adr-tools  # macOS
# or: npm install -g adr-tools

# Initialize the ADR directory
adr init docs/decisions

# Create a new ADR
adr new "Use Redis for session storage"
# Creates: docs/decisions/0014-use-redis-for-session-storage.md

# Supersede an old decision
adr new -s 0014 "Use JWT tokens instead of Redis sessions"
# Links the old ADR as "Superseded by 0015"

What Deserves an ADR?

Not every decision needs one. Good candidates:

  • Technology choices: “Why PostgreSQL and not MongoDB?”
  • Architecture patterns: “Why Event Sourcing for the orders domain?”
  • Trade-offs accepted: “Why we’re not using GraphQL”
  • Rejected alternatives: “We considered service mesh but decided not to”
  • Constraints accepted: “We will not support IE11”

Skip ADRs for:

  • Routine code structure decisions
  • Library version choices (unless there’s an interesting trade-off)
  • Anything that changes frequently

A good heuristic: if it would cause a 30-minute debate in a team meeting, write an ADR.

Writing Good ADRs

Be specific about context. “We need a database” is not context. “We’re building a system with 50M users, heavy read traffic, and complex relational data with financial transaction requirements” is context.

Document rejected alternatives. This is the most valuable part. If you don’t explain why you didn’t choose option B, the next person who joins will propose option B.

Be honest about consequences. ADRs aren’t press releases. The trade-offs you accept are as important as the benefits you gain.

Write them at decision time. ADRs written retroactively are useful but lose the nuance of the original debate. The best time to write one is when the decision is being made.

Superseding ADRs

When a decision changes, don’t delete the old ADR. Mark it superseded:

# ADR-0007: Use REST for internal service communication

## Status
Superseded by ADR-0019 — 2026-03-10

## Context
[original context...]

## Decision
[original decision...]

## Consequences
[...] Note: This decision was superseded when we adopted gRPC for
performance-sensitive internal services. See ADR-0019.

The history is valuable. You want to know that you tried REST first and why you moved on.

ADRs in Pull Requests

One of the best practices: require an ADR for significant architectural changes as part of the PR review. The template is in the repo. The reviewer checks whether the ADR captures the reasoning properly.

## PR Checklist
- [ ] Tests added/updated
- [ ] ADR created (for architectural changes)
- [ ] CHANGELOG updated

This makes the decision-making visible and forces engineers to articulate their reasoning before merging.

Key Takeaways

  • ADRs document why a decision was made, not just what was decided
  • Keep them short, keep them next to the code, keep them in version control
  • Document rejected alternatives — that’s often the most valuable part
  • Mark decisions superseded, never delete them — the history matters
  • Write ADRs at decision time, not retroactively
  • Require ADRs in PRs for significant architectural changes