Starphix
Software Engineering / Sources
The Lab / Sources / Software Engineering / Architecture/Architecture-Decision-Records.md

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/ or architecture/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

  • 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

From the Software Engineering research vault · CC BY 4.0 · all notes · raw markdown