Architecture Decision Records (ADRs)
An Architecture Decision Record (ADR) captures a significant architectural decision, its context, and consequences. ADRs create a decision log that provides project context and design rationale.
Why ADRs Matter
- Institutional memory — Decisions outlast the people who made them
- Onboarding — New team members understand why, not just what
- Accountability — Explicit trade-offs prevent "I didn't know" later
- Change management — Superseded ADRs show evolution of thinking
- Audit trail — Required in regulated environments
"Your architecture is the accumulation of its decisions, so the ADR is effectively a record of how and why the system came to be its current shape." — Microsoft Azure Well-Architected
ADR Lifecycle
PROPOSED → ACCEPTED → SUPERSEDED (by new ADR)
↓
DEPRECATED (if abandoned without replacement)
- Never edit an accepted ADR — it's immutable history
- If a decision changes, write a new ADR that supersedes the old
- Link the new ADR from the old one (and vice versa)
Standard ADR Template (Michael Nygard)
# ADR-XXX: [Title describing the decision, not the problem]
## Status
Proposed | Accepted | Superseded | Deprecated
## Context
What is the situation? What forces are at play?
- Technical constraints
- Business priorities
- Team skills/organization
- Timeline pressures
- Regulatory requirements
## Decision
What are we doing? Be specific and assertive.
- "We will use..."
- "We will adopt..."
- "We will not..."
## Consequences
### Positive
- Benefit 1
- Benefit 2
### Negative
- Cost/risk 1
- Cost/risk 2
### Neutral / Trade-offs
- Trade-off 1
## Alternatives Considered
| Alternative | Why Rejected |
|---|---|
| Option A | Reason |
| Option B | Reason |
## Related Decisions
- Supersedes: ADR-XXX
- Superseded by: ADR-YYY
- Related: ADR-ZZZ
## Metadata
- Date: YYYY-MM-DD
- Author(s): [names]
- Reviewers: [names]
- Confidence: High | Medium | Low
Lightweight Template (For Simpler Decisions)
# ADR-XXX: [Decision Title]
**Status**: Accepted
**Date**: YYYY-MM-DD
## Context
[1-2 paragraphs: what problem are we solving?]
## Decision
[The decision in one clear sentence]
## Consequences
- **Pros**: [...]
- **Cons**: [...]
- **Risks**: [...]
## Alternatives
[Brief list of what else was considered]
ADR Process Best Practices
1. Keep Meetings Short & Focused
- 30-45 minutes maximum
- Time-boxed readout (10-15 min reading, then discussion)
- Written comments on specific sections
2. Cross-Functional but Lean
- Invite reps from affected teams
- Keep total participants < 10
- Diverse perspectives, efficient decisions
3. One Decision Per ADR
- Split if multiple decisions emerge
- Concentrate on one thing at a time
- Reference design docs for exploration details
4. Separate Design from Decision
- Design docs explore options
- ADR records the chosen option
- Reference design docs from ADR
5. Resolve All Comments
- Incorporate changes OR discuss to consensus
- No unresolved comments at acceptance
- Demonstrates ownership and commitment
6. Push for Timely Decisions
- 1-3 readouts should suffice
- Most decisions are "two-way doors" (reversible)
- Better to decide and try than endlessly discuss
7. Centralize Storage
- Store in version control (Git) near the code
- Common location:
docs/adr/orarchitecture/decisions/ - Accessible to all project members
When to Write an ADR
Write an ADR for decisions that: - Affect system structure or key quality attributes - Are difficult or expensive to reverse - Involve significant trade-offs - Impact multiple teams or components - Set precedent for future decisions
Don't write ADRs for: - Daily operational calls - Implementation details within a settled architecture - Decisions that don't affect architecture
ADR File Organization
docs/
└── adr/
├── 0001-use-postgresql.md
├── 0002-adopt-hexagonal-architecture.md
├── 0003-api-versioning-strategy.md
├── 0004-event-driven-order-processing.md
├── 0005-supersede-0002-use-modular-monolith.md
└── README.md # Index with links and status summary
Naming: NNNN-short-description.md (zero-padded for sort order)
Index (README.md):
# Architecture Decision Records
| ID | Title | Status | Date |
|---|---|---|---|
| 0001 | Use PostgreSQL as Primary Database | Accepted | 2024-01-15 |
| 0002 | Adopt Hexagonal Architecture | Superseded | 2024-02-01 |
| 0003 | API Versioning Strategy | Accepted | 2024-02-10 |
| 0004 | Event-Driven Order Processing | Accepted | 2024-03-01 |
| 0005 | Use Modular Monolith (supersedes 0002) | Accepted | 2024-04-15 |
Example: ADR-0002
# ADR-0002: Adopt Hexagonal Architecture for Core Domain
## Status
Accepted (superseded by ADR-0005)
## Context
We're building the Order Management bounded context. The domain has complex business rules around pricing, discounts, and fulfillment. We need:
- High testability of domain logic
- Ability to swap persistence (PostgreSQL → DynamoDB for scaling)
- Clear separation from infrastructure
## Decision
We will implement the Order Management bounded context using Hexagonal Architecture (Ports & Adapters). The domain core will define inbound ports (use cases) and outbound ports (repositories, event publishers). Infrastructure adapters will implement these ports.
## Consequences
### Positive
- Domain logic testable without database/message broker
- Can swap PostgreSQL for DynamoDB by implementing new repository adapter
- Clear boundaries align with DDD bounded context
### Negative
- More boilerplate (interfaces, adapters, mappers)
- Indirection can obscure flow for new developers
- Initial setup slower than layered architecture
### Trade-offs
- Accepting initial velocity cost for long-term maintainability
- Team needs onboarding on pattern
## Alternatives Considered
| Alternative | Why Rejected |
|---|---|
| Layered Architecture | DB changes ripple to domain; hard to test in isolation |
| Clean Architecture | More layers than needed; similar benefits with more ceremony |
| Transaction Script | Doesn't handle domain complexity; leads to anemic model |
## Related Decisions
- Superseded by: ADR-0005 (Use Modular Monolith)
- Related: ADR-0001 (PostgreSQL), ADR-0004 (Event-Driven Processing)
## Metadata
- Date: 2024-02-01
- Author: Jane Architect
- Reviewers: Team Leads (Backend, QA, DevOps)
- Confidence: High
ADR Anti-Patterns
| Anti-Pattern | Fix |
|---|---|
| No ADRs | Start with first architectural decision |
| ADR as design doc | Keep ADR focused on decision; link design docs |
| Editing accepted ADRs | Write new superseding ADR instead |
| Vague consequences | Be specific: "adds 200ms latency" not "may impact performance" |
| Missing alternatives | Document what was considered and why rejected |
| Orphaned ADRs | Always link related/superseded ADRs |
| Private ADRs | Store in shared repo; make visible to all |
Tooling
| Tool | Purpose |
|---|---|
adr-tools (nathanleclaire) |
CLI for creating/managing ADRs |
adr-log |
Generate index from ADR files |
| GitHub/GitLab | Native rendering of markdown ADRs |
| Wiki (Confluence, Notion) | Alternative for non-technical stakeholders |
Related Notes
- Architectural Styles — Decisions often choose between styles
- Domain Driven Design — Bounded contexts drive ADRs
- Documentation Principles — ADRs as living documentation
- Engineering Culture — Blameless culture needs decision records
Sources: Michael Nygard (ADR origin), AWS Prescriptive Guidance, Microsoft Azure Well-Architected, Google Cloud Architecture Center, Thoughtworks Technology Radar, adr.github.io