Developer Productivity

Architecture Decision Records: Template and Best Practices

Implement Architecture Decision Records to document why you made important technical decisions. ADR template, examples, and workflow for software teams.

Back to blogApril 16, 20265 min read
documentationarchitecturedecisionsengineering

You make a technical decision.

"We're using PostgreSQL instead of MongoDB."

"We're adopting TypeScript."

"We're moving to microservices."

It's a good decision at the time.

Then: 18 months later, new team member asks, "Why PostgreSQL? Can we switch to MongoDB?"

You have to re-explain everything.

Or worse: you don't remember the tradeoffs anymore.

Context disappears.

Architecture Decision Records (ADRs) preserve that context.

An ADR is a lightweight document that captures:

  • What decision was made?
  • Why?
  • What were the alternatives?
  • What will be the consequences?

This guide shows you how to implement ADRs effectively.


Why ADRs Matter

Problem 1: Decision Context Disappears

You make decision. You remember it.

6 months later: You don't remember why.

12 months later: New people question it constantly.

ADRs preserve context for future you and your team.

Problem 2: Repeated Arguments

Same architectural question gets debated over and over.

Each time, you make the same decision.

Each time, someone questions it.

ADRs short-circuit repeated discussions.

Problem 3: Onboarding Paralysis

New engineer joins.

Wants to understand architecture.

Architecture decisions feel arbitrary.

No way to learn the why.

ADRs help new engineers understand the why behind the what.

Problem 4: Regret Without Evidence

You build something.

Later: "Why did we do this?"

You don't know. You re-decide (differently).

ADRs create an audit trail of decisions and their justification.


What an ADR Is

It's NOT:

  • A design document (too formal, too heavy)
  • Code comments (too scattered)
  • Slack conversations (too ephemeral)
  • Team wiki (unstructured)

It IS:

  • A lightweight record of a decision
  • Easy to write (15-30 min)
  • Easy to find (centralized, versioned)
  • Easy to understand (standard template)
  • Updateable (records can be amended)

ADR Template

Use this template for every architecture decision:

# ADR [NUMBER]: [TITLE]

## Date
[YYYY-MM-DD]

## Status
[Accepted/Proposed/Superseded/Deprecated]

## Context
What is the issue driving this decision?

[Explain the problem, constraints, context]

## Decision
What did we decide?

[State the architectural decision clearly]

## Rationale
Why this decision?

- Pro 1: [Benefit of this choice]
- Pro 2: [Benefit of this choice]
- Con 1: [Tradeoff or drawback]
- Con 2: [Tradeoff or drawback]

## Alternatives Considered

### Alternative 1: [Option A]
[Why we didn't choose this]

### Alternative 2: [Option B]
[Why we didn't choose this]

### Alternative 3: [Option C]
[Why we didn't choose this]

## Consequences

### Positive
- [What gets better]
- [What gets easier]

### Negative
- [What gets harder]
- [What we're giving up]

## Related Decisions
[Link to related ADRs]

Concrete Example

# ADR 001: Use PostgreSQL as Primary Database

## Date
2025-01-15

## Status
Accepted

## Context
We're building a SaaS product with relational data (users, accounts, permissions).

We need ACID compliance, complex queries, and strong schema validation.

Decision: PostgreSQL vs MongoDB

## Decision
Use PostgreSQL as our primary database.

## Rationale

### Pros
- ACID guarantees: Data consistency is critical for billing, permissions
- Complex queries: JOINs across users, accounts, transactions
- Strong schema: We benefit from typed validation
- Mature ecosystem: Great tools, strong community

### Cons
- Horizontal scaling: PostgreSQL doesn't scale horizontally as easily as MongoDB
- Schema migrations: Schema changes require explicit migrations
- Cost: Hosting PostgreSQL clusters costs more than document stores

## Alternatives Considered

### MongoDB
- Rejected: No ACID (until MongoDB 4.0, but still not as strong). Looser schema makes debugging harder. Wrong tool for relational data.

### DynamoDB
- Rejected: AWS vendor lock-in. Query patterns less flexible. More expensive for our scale.

### Cockroach DB
- Rejected: Good for scaling, but immature. Operational overhead not worth it at our scale.

## Consequences

### Positive
- Strong data consistency: Billing/permissions guaranteed correct
- Easier debugging: Schema is explicit, no surprises
- Mature tooling: Lots of libraries, frameworks, operational tools

### Negative
- Schema migrations required for changes: Extra process, some downtime
- Horizontal scaling harder: We'll hit single-node limits at some scale
- Higher operational knowledge required: Team needs PostgreSQL expertise

## Related Decisions
- ADR 002: API response caching strategy
- ADR 003: Database backup and recovery process

Types of Decisions Worth ADRing

Decision Type 1: Technology Choices

Examples:

  • Database choice (PostgreSQL vs MongoDB)
  • Framework choice (React vs Vue)
  • Language choice (Python vs Go)

Why ADR: These are major, long-lived decisions affecting architecture.

Decision Type 2: Architectural Patterns

Examples:

  • Microservices vs monolith
  • Event-driven vs synchronous APIs
  • Cache-first vs database-first reads

Why ADR: These drive the structure of the system.

Decision Type 3: Boundaries and Responsibility

Examples:

  • Authentication at API gateway vs in service
  • Rate limiting strategy (per IP, per user, per key)
  • How services communicate (HTTP, gRPC, queues)

Why ADR: These affect system design and integration patterns.

Decision Type 4: Non-Functional Requirements

Examples:

  • Data retention policy (keep 2 years, then archive)
  • Uptime target (99.9% vs 99.99%)
  • Encryption policy (encrypt at rest, in transit)

Why ADR: These have wide-ranging consequences.


When NOT to ADR

Skip ADR for:

  • Tiny internal decisions (code formatting, naming)
  • Reversible decisions (can easily undo)
  • Urgent decisions (capture later, format later)
  • Personal productivity choices

Use judgment: If it affects the team and it's not easily reversible, ADR it.


Implementation Workflow

Step 1: Create ADR Directory

docs/
├── adr/
│   ├── 001-database-choice.md
│   ├── 002-api-caching-strategy.md
│   └── README.md

Store ADRs in version control (Git).

Step 2: Number ADRs Sequentially

ADR 001, ADR 002, etc.

Use numbers for easy reference.

Step 3: Write ADR When Decision Is Made

Don't wait months.

Write while decision is fresh.

Step 4: Share with Team

Post for feedback.

Allow amendment during feedback period.

Once accepted, finalize.

Step 5: Update Links in Code

In related code, add comment:

// See docs/adr/001-database-choice.md for why we use PostgreSQL

Step 6: Update When Context Changes

If ADR is superseded by new decision:

## Status
Superseded by ADR 015

Don't delete. Keep historical record.


Common ADR Mistakes

Mistake 1: Too Formal/Bureaucratic

You write 5-page ADR for minor decision.

Team thinks this is too heavyweight.

ADRs never get written again.

Fix: Keep ADRs brief (1–2 pages). Template should take 15–30 min to fill.

Mistake 2: Written After the Fact

Decision was made 6 months ago.

You write ADR from memory.

Missing context and reasoning.

Fix: Write ADR immediately after decision is made, while context is fresh.

Mistake 3: No Alternatives Section

ADR just defends the choice.

Doesn't explain what was rejected and why.

Fix: Always include "Alternatives Considered" section.

Mistake 4: Never Updated

Architecture changes.

ADR becomes outdated.

New people read it, get confused.

Fix: Update ADR status when context changes. If superseded, note which ADR replaces it.

Mistake 5: No Consequences Section

ADR explains decision.

Doesn't explain what breaks or becomes harder.

Fix: Always document both positive and negative consequences.


ADR Examples in Practice

Example 1: Moving to Microservices

ADR 005: Adopt Microservices Architecture

Context: Monolith growing to 500k LOC. Deployment cycles slow.

Decision: Split into 3 services (auth, core, analytics)

Alternatives:
- Monolith with better CI/CD: Rejected, still too tightly coupled
- Fully distributed: Rejected, too complex for current team

Consequences:
+ Faster deployment per service
+ Teams can work independently
- Operational complexity (3 databases, 3 deployments)
- Network calls between services (latency)

Example 2: Using Redis for Caching

ADR 009: Use Redis for Caching

Context: Database queries slow. Need to cache frequently accessed data.

Decision: Use Redis cluster for cache

Alternatives:
- In-memory (application): Rejected, not shared across instances
- Memcached: Rejected, Redis has better data structures
- Database query cache: Rejected, not flexible enough

Consequences:
+ 10x faster reads for cached data
+ Flexible cache invalidation
- Extra infrastructure to operate
- Learning curve for team

Tools for ADRs

Option 1: Markdown in Git

Setup:

  1. Create docs/adr/ folder
  2. Write ADRs as .md files
  3. Commit to Git
  4. Reference in code comments

Pros: Simple, versioned, no extra tools

Cons: No fancy interface

Best for: Most teams

Option 2: GitHub Wiki

Setup:

  1. Create wiki in GitHub repo
  2. Write ADRs as wiki pages
  3. Link from READMEs

Pros: Easy to link, built-in to GitHub

Cons: Less versioned than markdown in repo

Option 3: Notion Database

Setup:

  1. Create database of ADRs
  2. Properties: Title, Status, Date, Tags
  3. Link from README

Pros: Beautiful interface, searchable

Cons: Not version-controlled with code

Best for: Non-technical stakeholders also need to read**


Checklist for Good ADRs

Before publishing, check:

  • Clear title (what decision?)
  • Context explains the problem
  • Decision is stated clearly
  • Rationale includes pros AND cons
  • Alternatives section explains what was rejected and why
  • Consequences section includes positive and negative
  • Status is clear (Accepted/Proposed/Superseded)
  • Date is included
  • Related ADRs are linked

Realistic Implementation

Week 1: Setup

  • Create docs/adr/ folder
  • Write ADR 001 for current architecture
  • Share template with team

Week 2–4: Capture

  • Add new ADRs as decisions are made
  • Update code comments to link to ADRs
  • Team gets familiar with template

Month 2+: Maintenance

  • Review ADRs during architecture discussions
  • Update when context changes
  • Use as reference during onboarding

Conclusion

ADRs preserve architectural decision context.

ADR template (simple version):

  1. Title: What decision?
  2. Context: What problem?
  3. Decision: What did we decide?
  4. Rationale: Why?
  5. Alternatives: What did we reject and why?
  6. Consequences: What are the tradeoffs?

When to write ADR:

  • Technology choices (database, framework, language)
  • Architectural patterns (microservices, caching, event-driven)
  • Design boundaries (API design, service responsibility)
  • Non-functional decisions (uptime SLA, retention policy)

How to start:

  1. Create docs/adr/ folder in your repo
  2. Write ADR 001 for your current architecture decision
  3. Share with team
  4. Use template for next decision
  5. After 3–4 ADRs, it becomes habitual

In 3 months, you'll have 6–10 ADRs capturing your architectural context. In 6 months, new team members will reference them constantly.

For developer documentation, see Developer Notes System. For team documentation culture, check Documentation Culture in Engineering Teams.

Document decisions. Preserve context. Build shared understanding.

Keep reading

More WebSnips articles that pair well with this topic.