Architecture Decision Record (ADR) Template
A lightweight template for documenting major architectural decisions, their context, options considered, and the reasoning behind the chosen approach.
Note: This guide follows English-language naming conventions and terminology standards common in international development teams. Examples use English identifiers and comments to maximize compatibility across codebases and tooling.
Overview
Every major architectural decision creates context that fades within months. Why did we choose PostgreSQL over 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.
When to Use
- For alternatives, see Engineering Handbook Template.
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 multiple 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”
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 is attractive]
- **Cons:** [Why it is 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 does not 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 |
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 is too long
- Link related ADRs — decisions do not exist in isolation; show the chain of reasoning
- Accept deprecation — mark ADRs as superseded when better options emerge; do not 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
Troubleshooting
- High latency between services: trace the request path. Look for synchronous chains, missing caching, and oversized payloads that cross network boundaries.
- Single point of failure: identify components without redundancy. Add replicas, failover, or circuit breakers before scaling traffic.
- Unexpected coupling between services: review shared databases, libraries, and schemas. Bound contexts should own their data and expose stable interfaces.
- Cost spikes after scaling: right-size instances and use autoscaling with limits. Reserved capacity or spot instances can reduce steady-state spend.
- Difficult to reason about the system: maintain architecture decision records and service dependency maps.
Quick Reference
- Main command: run the base solution from the article and verify the expected result.
- Validation: confirm tests pass and key metrics did not degrade.
- Rollback: if something fails, revert the change and consult the Troubleshooting section.
Further Reading
- Official documentation: check the current reference for the framework or tool used.
- Related guides: explore the adr and architecture guides for deeper coverage.
- Complementary patterns: review design patterns applicable to your technology stack.
- Public postmortems: study real incidents from teams that faced similar production issues.
Production Notes
- Deploy gradually using canary or blue-green to catch regressions early.
- Configure alerts for error rate, p99 latency, and failure rate before enabling in production.
- Document the rollback in the runbook; test the procedure in staging at least once per quarter.
- Review structured logs with correlation IDs to trace requests end-to-end during incidents.
Key Takeaways
- Apply architecture decision record (adr) template when you need a practical solution for your use case.
- Monitor performance after implementation; measure latency, errors, and resource usage before and after.
- Check the Troubleshooting section for common failures; most have documented root causes with fixes.
- Keep dependencies updated and run tests in CI to prevent production regressions.
Common Production Pitfalls
- Leaving required fields blank or using vague one-word answers.
- Filling the document once and never updating it after scope or decisions change.
- Storing the document where the team does not look during incidents or reviews.
- Not assigning an owner, due date, or review cadence.
- Copying boilerplate without removing sections that do not apply.
- Skipping version control, which makes rollback and accountability impossible.
- Failing to link the document to related decisions or follow-up actions.
- Avoiding quarterly reviews that would retire stale or unused sections.
Related Resources
Feature Specification Template
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.
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...
- Who should write the ADR?
- The person or team proposing the decision writes the first draft. Stakeholders who will be affected by the decision should review and approve it. The author does not need to be the most senior...
- When should an ADR be updated?
- Update the status when the decision is accepted, deprecated, or superseded. Update the content when new information changes the trade-offs (e.g., a previously rejected option becomes viable). Do not...
- 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...
- 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...
- 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...
- 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...
- 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...