Architecture Decision Record (ADR)
Guides agents to record “under which constraints we chose B over A” with fixed headings so future readers see historical trade-offs, not only current code.
An ADR answers “why we decided this then,” not a README replacement; link issues/PRs and keep the body self-contained. When drafting, align numbering rules and storage path first, then context and alternatives, then verifiable consequences and review triggers.
When to write an ADR and decision flow
Open an ADR for choices that are hard to roll back or define cross-team contracts (data model, public API, deployment topology, compliance boundary); local implementation detail can stay in the PR. Below: from tension signal to supersession chain.
[ Tension signal: performance / cost / compliance / maintainability / skills ]
│
▼
[ Draft: constraints + options + recommendation ]
│
▼
┌──────────┴──────────┐
▼ ▼
[ Sync review or async comments ] [ Need PoC / benchmark? ]
│ │
└──────────┬──────────┘
▼
[ Decision: proposed / accepted / deferred / rejected ]
│
▼
[ Persist: number + slug filename + link related ADRs / issues ]
│
▼
[ After implementation: record positive/negative effects + metrics ]
│
▼
[ If superseded: status → superseded, point to new ADR number ]
- Choosing a database type, message queue, or authentication scheme as infrastructure
- Public API design or protocol selection (REST vs gRPC vs GraphQL)
- Cross-service data model change or dependency direction adjustment
- Compliance / security boundary decision (encryption algorithm, data residency)
ADR directory structure and file naming convention:
# docs/adr/ directory structure
docs/
adr/
README.md # explains numbering rules and status definitions
0001-use-postgresql-as-primary-db.md
0002-use-kafka-for-event-streaming.md
0003-adopt-jwt-for-api-auth.md
0042-migrate-to-graphql.md # status: superseded → see ADR-0051
0051-adopt-rest-with-openapi.md # status: accepted, supersedes ADR-0042
# Status transition example (ADR front matter)
---
status: accepted # proposed | accepted | deprecated | superseded
date: 2025-03-15
deciders: [tech-lead, dba, backend-team]
supersedes: [] # which old ADRs this ADR supersedes
superseded-by: "" # if this ADR is superseded, fill in new ADR number
---
Writing tips and status
Suggested status values: proposed, accepted, superseded, deprecated; when superseded, link the new ADR number and keep the chain traceable.
The decision section should be actionable: note key config or interface shape for the chosen option; alternatives get a short rejection reason (cost, risk, team skills).
Consequences split positive, negative (with mitigations), and metrics/alerts to watch; negatives should map to mitigation or a registered “known debt.”
- Numbering: global increment or subsystem prefix—team agrees.
- Review: optional sign-off from tech lead or architecture review.
- Expiry: conditions that force reopening (traffic tier, regulatory change, etc.).
Real ADR excerpt example (choosing a message queue):
# ADR-0002: Use Apache Kafka as the event streaming platform
## Metadata
- Status: accepted
- Date: 2025-04-01
- Deciders: [platform-team, backend-leads]
## Context
Order service needs to push events in real time to three downstream services:
inventory, logistics, and notifications. Currently uses REST callbacks;
adding new consumers requires changes upstream—high coupling.
Peak daily message volume expected at 5M/day; needs persistence and replay.
## Options considered
### Option A — Apache Kafka
- Pro: high throughput, persistence, independent consumer group offsets, supports replay
- Con: high operational complexity; requires ZooKeeper/KRaft
### Option B — RabbitMQ
- Pro: simpler operations, intuitive queue semantics
- Con: no disk persistence by default; no replay; throughput questionable at this scale
### Option C — Continue REST callbacks
- Con: tight coupling; adding consumers requires upstream changes; no message persistence
## Decision
Option A (Kafka). 5M/day peak + replay requirement makes Kafka's ops cost justified.
Key config: 3 brokers + replication.factor=3 + min.insync.replicas=2.
## Consequences
### Positive
- Consumers decoupled; adding new consumers requires no upstream changes
- Messages persisted for 7 days; supports replay and reprocessing
### Negative and mitigations
- Operational complexity: adopt Kafka Operator (Strimzi); use managed MSK in cloud
- Message ordering: guaranteed only within partition; use order_id as partition key
### Metrics to monitor
- consumer_lag > 10,000 → alert
- broker disk usage > 70% → alert
## Review and invalidation
- If daily message volume exceeds 50M, re-evaluate partition count
- If Kafka managed service cost exceeds budget by 20%, evaluate Pulsar as alternative
ADR section template
Copy this Markdown skeleton into docs/adr/; add “Compliance,” “Links,” etc. per team habit.
---
name: adr-authoring
description: Draft ADR Markdown skeleton
---
# ADR-NNN: <short title>
## Metadata (optional YAML front matter or table)
- Status: proposed | accepted | superseded | deprecated
- Date: YYYY-MM-DD
- Deciders: <roles or names>
- Supersedes: <if any, link ADR-MMM>
- Superseded by: <if any>
## Context and problem statement
- What business or technical driver?
- Worst case if we do not decide?
- Scope: in / explicitly out
## Decision drivers
- Hard constraints (SLA, budget, compliance, deadlines)
- Priority order (e.g. correctness > cost > speed)
## Options considered
### Option A
- Summary, dependencies, estimated cost and risk
### Option B
- …
## Decision
- Chosen option (A/B/…) and one-line rationale
- Key interfaces, config, or data shape (enough for implementers)
## Consequences
### Positive
### Negative and mitigations
### Metrics or alerts to monitor
## Review and invalidation
- When this ADR must be reopened (traffic threshold, regulatory change, upstream deprecation, etc.)
## Related links
- Issue / PR / RFC / runbook
Title slug and filename
Extract Latin letters and digits from the title into kebab-case for NNN-slug.md. Pure non-Latin titles may not auto-slug—keep English keywords in the title or a separate short name.
Generation and copy run locally in the browser only. Slug rule: consecutive Latin tokens/digits lowercased and joined with hyphens.
---
name: adr-authoring
description: Draft architecture decision record Markdown skeleton
---
# Steps
1. Confirm numbering rules and docs/adr path
2. Fill context, options, decision, consequences
3. Write slug filename and link related ADRs / issues