Architecture Decision Record (ADR) Template
A lightweight template for documenting major architectural decisions, their context, options considered, and the reasoning behind the chosen approach.
Overview
Every major architectural decision creates context that fades within months. Why PostgreSQL and not MongoDB? Why is the service mesh Envoy and not Linkerd? Why do we shard by tenant ID? Without written records, new engineers re-litigate old decisions, teams repeat rejected approaches, and managers make plans that conflict with technical constraints. An Architecture Decision Record (ADR) is a single document that captures the context, options, trade-offs, and consequences of a major technical choice. Related resources: Design a Scalable API Gateway for Microservices, Build Resilient Systems with the Circuit Breaker Pattern, and Dependency Injection.
When to Use
Use this template when:
- A decision affects more than one team or service
- The decision is hard to undo or will be expensive to reverse
- You evaluated several options and need to explain why one won
- You expect the decision to be questioned or revisited in the future
- Onboarding new engineers who need to understand “why the system works this way”
- For process-level documentation instead of decisions, see the engineering handbook template
Prerequisites
Before writing an ADR:
- Confirm the decision is major enough to document (not every PR needs an ADR)
- Gather input from stakeholders who will be affected by the decision
- Document options you seriously considered, not just the winner
- Identify who has authority to approve or overturn the decision
- Choose where ADRs live (Git repo
/docs/adr/, wiki, or dedicated docs site)
Solution
# ADR-XXX: `<Title of Decision>`
| Field | Value |
|-------|-------|
| Status | Proposed / Accepted / Deprecated / Superseded by ADR-YYY |
| Date | YYYY-MM-DD |
| Author | ______ |
| Deciders | ______ |
| Tags | ______ |
## 1. Context and Problem Statement
[What is the problem or opportunity that triggered this decision? What forces are at play, including technical, business, and team constraints? What happens if we do nothing?]
## 2. Decision Drivers
- [Driver 1: e.g., must support 10x traffic growth within 2 years]
- [Driver 2: e.g., team has deep expertise in X but not Y]
- [Driver 3: e.g., compliance requirement for data residency]
- [Driver 4: e.g., must integrate with existing systems without breaking changes]
## 3. Considered Options
### Option 1: [Name]
- **Description:** [What is it?]
- **Pros:** [Why it's attractive]
- **Cons:** [Why it's risky or problematic]
- **Effort:** [Rough estimate: small / medium / large]
### Option 2: [Name]
- **Description:**
- **Pros:**
- **Cons:**
- **Effort:**
### Option 3: [Name]
- **Description:**
- **Pros:**
- **Cons:**
- **Effort:**
## 4. Decision
**Chosen option:** [Option X]
**Rationale:** [Why this option wins. Reference the decision drivers — which ones does it satisfy best?]
**Trade-offs accepted:** [What are we giving up by choosing this option?]
## 5. Consequences
### Positive
- ______
- ______
### Negative
- ______
- ______
### Risks
- ______
### Mitigations
- ______
## 6. Implementation Notes
- [Step 1: ______]
- [Step 2: ______]
- [Step 3: ______]
## 7. Related Decisions
| ADR | Relationship |
|-----|-------------|
| ADR-___ | Supersedes / Depends on / Conflicts with / Complements |
## 8. Change Log
| Date | Change | Author |
|------|--------|--------|
| YYYY-MM-DD | Proposed | ______ |
| YYYY-MM-DD | Accepted | ______ |
Explanation
The ADR format is intentionally lightweight. It doesn’t require UML diagrams or formal proofs — just enough structure that someone reading it in two years understands why the decision was made and what was sacrificed. The status field is critical: it tells readers whether the decision is active, outdated, or replaced. The consequences section prevents the common mistake of documenting only the happy path; every architectural choice has downsides, and hiding them creates surprises later.
Full ADR Example
# ADR-015: Migrate to PostgreSQL as primary data store
## Status
Accepted (2026-07-11)
## Context
The application has used MySQL 5.7 since 2023. With team and data growth, we have hit limitations:
- No JSONB support or native JSON queries
- Limited logical replication compared to PostgreSQL
- No declarative partitioning
- MySQL Enterprise licensing costs
The platform team needs table-level partitioning to handle the events table growth (currently 2TB, growing 50% annually).
## Decision
Migrate to PostgreSQL 16 as the primary database.
## Alternatives Considered
### 1. Stay on MySQL 8.0
- Pros: Simpler migration, team familiarity
- Cons: Weaker JSONB, limited partitioning
- Rejected: Does not solve partitioning requirement
### 2. Migrate to Amazon Aurora PostgreSQL
- Pros: PostgreSQL compatible, managed, global replication
- Cons: Higher cost, vendor lock-in
- Deferred: Evaluate after self-managed PostgreSQL migration
### 3. Migrate to CockroachDB
- Pros: Distributed, PostgreSQL-compatible SQL
- Cons: Cost, complexity, no team experience
- Rejected: Over-engineering for current needs
## Consequences
### Positive
- Native declarative partitioning
- JSONB for semi-structured data
- Solid logical replication
- Active community and mature tooling (pgAdmin, pgBackRest)
### Negative
- Team learning curve (2-4 weeks)
- Need to migrate MySQL-specific queries
- Different monitoring tools (pg_stat_statements vs slow query log)
### Mitigations
- Team training on PostgreSQL before migration
- Use pgloader for automatic schema and data migration
- Keep MySQL in parallel for 30 days as fallback
## Implementation Notes
1. Phase 1: Set up PostgreSQL in staging, migrate schema with pgloader
2. Phase 2: Migrate data in staging, run application tests
3. Phase 3: Migrate production with planned downtime (maintenance window)
4. Phase 4: Monitor for 30 days, decommission MySQL
## Related Decisions
| ADR | Relationship |
|-----|-------------|
| ADR-008 | Depends on (database monitoring) |
| ADR-012 | Complements (backup strategy) |
## Change Log
| Date | Change | Author |
|------|--------|--------|
| 2026-07-04 | Proposed | alice@example.com |
| 2026-07-11 | Accepted | platform-team |
The ADR Lifecycle
| State | Meaning | Action |
|---|---|---|
| Proposed | Drafted, under review | Circulate, gather feedback |
| Accepted | Approved and active | Implement, link from docs |
| Deprecated | No longer active, not replaced | Mark with date and reason |
| Superseded | Replaced by a newer ADR | Add superseded-by link, keep original |
Most ADRs live two lives: a few days in Proposed, then years in Accepted. The tail states matter more than people expect — a deprecated ADR nobody marked is worse than no ADR, because readers trust it. Never delete an ADR: the trail is the value.
When NOT to Write an ADR
Not every decision deserves a record. Skip the ADR when:
- The choice is reversible in an afternoon — swapping a lint rule, renaming a package
- The decision is personal, not architectural — which editor, how to name a variable
- A ticket already captures it — one-off tasks with no future reader
- You’re documenting the how, not the why — that belongs in a runbook
The test: will anyone in two years ask “why did they do it this way?” If yes, write the ADR.
Rolling Out ADRs Across a Team
Introducing ADRs to a team that never used them fails predictably: someone writes a wiki page, two people adopt it, six months later there are four ADRs and nobody remembers the convention. What works instead:
- Seed with history — pick the five decisions everyone argues about and backfill ADRs. Instant index, instant value.
- Attach to the existing flow — the PR template asks “does this need an ADR?”; a checkbox, not a meeting.
- Keep the bar low — first ADRs are ugly and that’s fine; a short record that exists beats a perfect template nobody fills.
- Review visibly — read one old ADR aloud in a team meeting; the day someone says “we don’t do that anymore” is the day the practice pays for itself.
Past fifty ADRs the practice changes shape: the folder needs an index grouped by subsystem, titles start carrying the search weight, and deprecated records move to an archive/ subfolder so the active set stays scannable.
The Decision Log as an Asset
A folder of thirty ADRs is worth more than the sum of its pages. Query it before architecture reviews: “what did we decide about message ordering?” becomes a searchable answer instead of a rumor. Use it in onboarding — new engineers read the decision log before the codebase, because the code shows what exists while the log explains why it exists. And use it in incident reviews: when the postmortem asks “how did we end up with this design?”, the ADR trail either answers or reveals that a critical decision was never recorded — which is itself a finding worth an ADR.
The log also disciplines future proposals. A team that can link ADR-023 to show “we already rejected this and here’s why” stops re-litigating settled questions; the rejection is archived with its reasoning, so the conversation moves to what changed since, not to starting over. That is the compounding return of the practice: decisions stop being re-made and start being built on.
What the Template Deliberately Omits
The ADR format has no executive summary, no Gantt chart, no stakeholder sign-off matrix — and that’s intentional. Documents that demand ceremony get written once and abandoned; the ADR survives because its cost is an honest hour of writing, not a week of formatting. If your org needs the heavier apparatus (cost estimates, legal review, rollout schedules), bolt it on as an org-level variant — the Variants table above has the pattern — but resist putting it in the base template. The base template’s job is the minimum structure that preserves why; everything else is local policy.
One omission worth defending explicitly: no “recommendation score” or weighted decision matrix. Scoring matrices look objective but encode the author’s preferences in the weights — the ADR asks for the reasoning in prose instead, because prose can’t hide a bad argument behind arithmetic.
Keeping ADRs Findable
An ADR nobody can find is an ADR nobody follows. Three habits keep the log navigable: sequential numbering that never recycles (ADR-042 stays ADR-042 even if superseded — the number is the citation), a README.md index in the ADR folder grouped by subsystem rather than by date, and links from where people actually look — the service README, the onboarding doc, the runbook that runs the affected system. When an ADR is superseded, the old file keeps its place in the index with a struck-through status; the reader who lands there from an old link should see, in one glance, “this is history — go to ADR-051 instead.”
A Note on Timing
Write the ADR while the reasoning is still warm — ideally the same week the decision settles, never quarters later. Late ADRs aren’t useless (a backfilled record beats an oral legend), but they reconstruct the winning option’s case far better than the losing ones, because the losers’ arguments die undocumented. If you’re backfilling, say so in the record: “written in retrospect” is honest metadata that tells the reader to discount the confidence of the alternatives section accordingly.
There’s one more moment worth recording that nobody puts in the template: when the decision stops being re-asked. The ADR that ends a three-year recurring debate is the one that paid for the whole practice — note it in the changelog, link the settled debate, and let the record close the loop it was written to close.
One more adaptation worth naming: when the ADR is wrong. Not superseded — wrong, as in the chosen option failed and everyone knows it. The temptation is to quietly revise the context so the decision looks better in hindsight; resist it. An ADR that documents a bad call with honest reasoning is still doing its job — it shows the organization how the decision actually looked when it was made, which is the only way the next decision gets smarter. The failure belongs in the postmortem; the record belongs untouched, with a Superseded status pointing at whatever came next. The teams that document their misses end up with fewer of them — not because the record prevents mistakes, but because it makes the pattern of mistakes visible enough to actually fix — and that feedback loop, not any single template, is what the whole practice is for, in the end.
How to Review an ADR
Reviewing a decision record isn’t copyediting. The questions a reviewer answers:
- Is the context falsifiable? “We need scale” is noise; “we peak at 4k orders/minute and the sync call adds 300ms” is a constraint someone can challenge.
- Are the alternatives real? Every rejected option needs a reason that still makes sense next year.
- Does the decision follow from the context? If a stranger can read the context and pick a different option, the context is missing something.
- Are the consequences honest? An ADR with only positive consequences was written to win an argument, not to document a decision.
Variants
| Context | Adjustments | Notes |
|---|---|---|
| Team-level ADR | Shorter; focus on local scope and immediate trade-offs | Not every decision needs org-level buy-in |
| Org-level ADR | Add approval section, cost estimates, and migration timeline | Cross-team decisions need explicit sign-off |
| Infrastructure ADR | Add capacity planning, runbook impact, and operational burden | Infrastructure choices are hard to undo |
| Security ADR | Add threat model, compliance mapping, and security review sign-off | Security decisions need explicit approval |
| Deprecation ADR | Document why an old decision is being reversed and what replaces it | Deprecation deserves its own ADR |
What Works
- Number ADRs sequentially —
ADR-001,ADR-002— so references are unambiguous - Store ADRs in version control — they should be reviewed, approved, and tracked like code
- Keep them short — if it takes more than 10 minutes to read, it’s too long
- Link related ADRs — decisions don’t exist in isolation; show the chain of reasoning
- Accept deprecation — mark ADRs as superseded when better options emerge; don’t delete them
Common Mistakes
- Writing ADRs for everything — not every PR or library upgrade needs an ADR; reserve them for major, irreversible choices
- Only documenting the winner — future readers need to know what was rejected and why, or they will propose it again
- Hiding negative consequences — every decision has trade-offs; documenting them builds trust and prevents surprises
- Letting ADRs go stale — update status to “Deprecated” or “Superseded” when decisions change
- Making them hard to find — ADRs should be linked from READMEs, onboarding docs, and architecture overviews
Further Reading
- Michael Nygard — Documenting Architecture Decisions — the 2011 post that defined the format
- ADR Organization — templates, tooling, and index of ADR practice
- adr-tools — CLI for scaffolding and linking ADRs
Frequently Asked Questions
How is an ADR different from a design doc?
A design doc describes how to build something. An ADR records why a particular approach was chosen over alternatives. Design docs are implementation plans; ADRs are decision logs. A large project may have one design doc and several ADRs.
Who should write the ADR?
The person or team proposing the decision writes the first draft. Anyone the decision affects should review and approve it. The author doesn't have to be the most senior engineer — just someone who understands the options and trade-offs.
When should an ADR be updated?
Update the status when the decision is accepted, deprecated, or superseded. Refresh the content when new info shifts the trade-offs (say, a previously rejected option becomes viable). Do not edit accepted ADRs to rewrite history — append a changelog entry instead.
How do we organize ADRs in the repository?
Create a docs/adr/ directory in the repository. Name each file ADR-NNN-short-descriptive-title.md (e.g., ADR-015-migrate-postgresql.md). Maintain a README.md in the directory that lists all ADRs with their current status. Link related ADRs with relative links. Add the ADR directory to onboarding documentation so new engineers can review past decisions. Consider using a tool like adr-tools to scaffold and link ADRs automatically.
When should an ADR be superseded?
An ADR should be superseded when: the chosen technology reaches end of life, a new option becomes clearly superior, requirements changed considerably, or the decision caused operational issues that outweigh benefits. Do not edit the original ADR — create a new ADR that references the old one, mark the old one's status as "Superseded by ADR-NNN", and explain why the change is being made. Keep the old ADR in the repo — it's your decision history.
How do we integrate ADRs with the pull request workflow?
When a pull request introduces a significant architectural change, require an ADR as part of the PR. The ADR is reviewed alongside the code. Use a PR template that asks: "Does this PR introduce an architectural change? If yes, link the ADR." Tag PRs with ADRs so they're easy to find. Require platform or architecture team approval for org-level ADRs. For team-level ADRs, peer review is sufficient.
What tools exist for managing ADRs?
Popular tools: adr-tools (CLI for creating and linking ADRs), log4brains (static site generator for ADRs), adr-viewer (web viewer for markdown ADRs), and backstage (developer portal platform with ADR support). You can also use plain markdown in a versioned directory — simplicity is an advantage. The best tool is whatever your team actually uses. Start with plain markdown and adopt tools if management becomes manual.
How do we prevent ADRs from going stale?
Review ADRs quarterly during architecture reviews. Verify the status is correct (Accepted, Deprecated, Superseded). For ADRs older than 2 years, check if the decision is still relevant. If the chosen technology is no longer used, mark the ADR as "Obsolete". When a new decision replaces an old one, flip the old ADR's status right away. Assign an owner to each ADR who is responsible for keeping its status current — include ADR review in the architecture review checklist.
How do we foster an ADR culture in the team?
Start with a workshop where the team writes an ADR together for a recent decision. Weave ADRs into the review process: add a step in the PR template asking whether an ADR is needed. Celebrate good ADRs in team retrospectives. Keep the process light — if an ADR takes more than 30 minutes, the process is too heavy. Share new ADRs in the team channel for visibility, and name a senior engineer as "ADR champion" to answer questions and hold the quality bar.
Related Resources
Feature Spec Template (Copy-Paste + Example)
A template for writing clear, actionable feature specifications that align engineering, product, and design before development begins.
DocEngineering Handbook Template
A template for documenting team culture, development processes, technical standards, and operational practices in a single referenceable handbook.
DocSystem Diagram Template
A template for creating C4 model and architecture diagram standards.
DocIncident Postmortem Template
A blameless postmortem template for documenting incidents: timeline, impact, root cause, contributing factors, and action items with owners.
DocTechnical Specification Template
Use this technical specification template to document requirements, design decisions, architecture, API contracts, and acceptance criteria.