Architecture Decision Record (ADR) Template
Updated: Aug 6
I once spent the better part of a day trying to figure out why a service talked to the database through a hand-rolled connection pool instead of the framework's built-in one. The person who wrote it had left. Git blame gave me a commit message that said "add pooling." Slack search turned up nothing. I eventually rebuilt the reasoning from a load-test spreadsheet buried in a shared drive — the framework pool leaked connections under a specific failover scenario, and the custom pool was a deliberate workaround, not the accident I'd assumed it was. I almost reverted it. A four-sentence ADR would have saved me the day and saved production the outage my "cleanup" would have caused.
That is the whole case for ADRs: the reasoning behind a decision decays faster than the code that encodes it. This guide is a template that captures the reasoning before it evaporates.
What an ADR Captures
An ADR is a short document recording a single architectural decision. Key word: single. One ADR per decision. Bundling multiple decisions into one document defeats the purpose.
What it captures:
The decision itself
The context that produced it
The forces at play (constraints, requirements, options considered)
The consequences you accept, including downsides
What it doesn't capture:
Implementation details (those live in code and docs)
Project-level information (timelines, owners — those live in the project tracker)
Marketing or business reasoning (those belong elsewhere)
The Template
# ADR-NNN: [Short, descriptive title]
Date: YYYY-MM-DD
Status: [Proposed / Accepted / Deprecated / Superseded by ADR-XXX]
## Context
[What's the situation? What problem are we solving? What constraints apply?]
## Decision
[What did we decide? Specific, declarative.]
## Alternatives Considered
[What did we look at and reject? Why?]
## Consequences
[What follows from this decision? Both good and bad.]
That's it. Five sections. Most ADRs are 1-2 pages. Longer ones are usually padding.
Numbering and Naming
Number ADRs sequentially in your repo. ADR-001, ADR-002. The number never changes; if you supersede an ADR, the new ADR gets a new number and the old one's status changes to "Superseded."
Title should be a short noun phrase, descriptive enough to scan. "Use PostgreSQL for primary data store" is good. "Database decision" is bad. "Use Postgres because of the various advantages it provides over alternatives like MySQL" is too long.
Status
The status field tells you whether to trust the ADR.
Proposed: Under discussion, not yet adopted.
Accepted: This is the current decision.
Deprecated: No longer the recommended approach, but old code may still reflect it.
Superseded by ADR-XXX: Replaced by another decision. Link to it.
Never delete an ADR. Even outdated decisions are part of the history. Mark them Superseded or Deprecated and move on.
Context
The context section explains why this decision needed to be made at this time. What changed? What problem appeared? What did the team know that prompted the decision?
Bad: "We need a database."
Good: "Our user load grew 10x in six months. The current SQLite-based persistence layer doesn't support concurrent writes at this scale. We need to choose a primary data store that scales to the next 10x and provides operational maturity for a team that has limited ops capacity."
The context tells future readers what assumptions the decision is based on. When those assumptions change, the decision may need revisiting.
Decision
State the decision clearly and specifically. One sentence is often enough.
"We will use PostgreSQL 15 as the primary data store, deployed via managed RDS, with read replicas in the same region."
Avoid hedging language. "We are considering using" is not a decision. "We will use" is.
Alternatives Considered
The most undervalued section, and the one I'd argue is the actual point of the whole document. If your "Alternatives Considered" is empty, you didn't make a decision — you had a reflex, and reflexes don't deserve an ADR. List what you looked at and rejected, with one or two sentences per alternative explaining why.
This serves three purposes:
Shows the decision was deliberate, not arbitrary
Helps future readers understand why the obvious alternative isn't being used
Lets you revisit alternatives if the original decision needs to be reconsidered
Example:
MySQL: Considered. Comparable feature set. PostgreSQL chosen for stronger JSON support and better extension ecosystem. DynamoDB: Considered. Lower operational overhead. Rejected because the existing queries depend heavily on joins that don't translate to a key-value model. MongoDB: Considered. Document model fits some use cases. Rejected because the team's existing expertise is relational and we need to ship quickly.
Consequences
What follows from this decision. Both positive and negative.
The positive consequences are usually obvious — they're why you made the decision. The negative ones are critical. Be honest about what you're accepting.
Example:
Positive: Negative:
Strong ACID guarantees support our consistency needs.
Existing team familiarity reduces learning curve.
Rich ecosystem for tooling and extensions.
Operational overhead higher than a NoSQL alternative — we'll need to invest in monitoring, backup, and HA configuration.
Vertical scaling will eventually be a constraint; cross-region sharding will be needed if we 100x.
Locks us into relational schema design; migration to a different model later would be expensive.
The negative consequences should be specific enough to plan around. Vague worries are useless; specific accepted trade-offs are useful.
When to Write an ADR
Write one for any decision that:
Affects how multiple components or teams work
Locks in a constraint that's expensive to reverse
Picks one option from several legitimate alternatives
Would be questioned by a new engineer joining the team
Don't write one for:
Routine implementation choices (loop type, variable naming, file structure)
Decisions with only one obvious answer (use HTTPS, use git)
Project-specific decisions that don't outlast the project
The signal: "if someone asked why we did this, would 'because we did' be an inadequate answer?" If yes, write the ADR.
Where to Keep Them
A docs/adr/ directory in the relevant repo. Each ADR is a markdown file: 001-use-postgresql.md, 002-event-sourcing-for-orders.md, etc.
The reason for keeping them in the repo: they version with the code. Branches, history, and review all apply. The ADR review is a normal PR.
For decisions that span multiple repos, choose the most relevant one (often the primary service) or maintain a central "architecture" repo with cross-cutting ADRs.
Reviewing ADRs
ADRs go through review like code. A proposed ADR gets:
Technical review (does the decision make sense?)
Trade-off review (are the alternatives fairly considered?)
Consequence review (are the downsides honestly captured?)
The review process catches half-formed decisions. If you can't write a defensible ADR, the decision probably needs more thinking.
Anti-Patterns
Retroactive ADRs. Writing an ADR after the decision is implemented, to document it for the audit. Often valuable for legacy decisions, but the timing means the ADR reflects what was done, not what was actually decided. Mark it clearly.
Decision-by-document. Long ADRs that prevent decisions rather than recording them. The point is to decide; the document is the artifact, not the process.
Status drift. ADRs that say "Accepted" but no one actually follows them. Either update the status or update the practice.
Bundled decisions. "ADR-005: Database, caching, and queue technology choices." Three decisions. Three ADRs.
Implementation in the ADR. The ADR captures the decision; the implementation lives in code and docs. Mixing them produces documents that don't age well.
Living with ADRs Over Time
The first ADRs are easy to write — there's no precedent. The fiftieth is harder. Some practices that help over time:
Periodic review. Quarterly or annually, walk the ADR list. Which are still current? Which are superseded but not marked?
Index by topic. A README in the ADR directory grouping by area (data, deployment, security, etc.).
Search-friendly titles. A good title surfaces in a search; a vague one doesn't.
Link from code. Where a non-obvious decision is reflected in the code, a comment can link to the ADR.
A Worked Example
# ADR-014: Use JWT Access Tokens with 15-Minute Expiry
Date: 2026-03-12
Status: Accepted
## Context
Our session management currently uses opaque server-side session IDs stored in Redis. As we move to a microservices architecture with multiple backend services, every service needs to validate sessions, which has caused both performance issues (Redis becoming a bottleneck) and operational complexity (each service needs Redis access).
## Decision
We will use JWT access tokens for inter-service authentication, signed with our internal keypair, with a 15-minute expiry. Refresh tokens remain server-side, opaque, stored in Redis. The auth service is the only service that touches Redis directly.
## Alternatives Considered
**Continue with opaque sessions:** Familiar pattern. Rejected because the cross-service Redis dependency conflicts with our microservices goals.
**Longer-lived JWTs (24h):** Considered. Rejected because revocation becomes hard; a stolen token is valid for 24 hours.
**Stateless JWTs without refresh:** Rejected because revocation is impossible without a denylist, which defeats statelessness.
## Consequences
**Positive:**
- Services validate tokens without external state
- Redis bottleneck removed from the hot path
- Standard pattern, well-supported in libraries
**Negative:**
- Token revocation requires waiting up to 15 minutes for expiry
- JWTs carry more bytes than session IDs (network overhead)
- Key rotation needs careful handling
- Risk of overloaded claims (we'll need explicit governance on what goes in tokens)
That's a complete ADR. Half a page. Easy to write, easy to read, durable.
Key Takeaway
ADRs capture single architectural decisions: context, decision, alternatives, consequences. Most are 1-2 pages. They live in the repo, version with the code, and survive turnover. Write one for any decision that locks in a trade-off, affects multiple components, or would warrant a "why" from a new engineer. The most valuable section is alternatives considered — it shows the decision was deliberate and helps future readers. Keep ADRs current: mark superseded ones, update statuses, never delete. The investment is small; the payoff is institutional memory that doesn't depend on people remembering.


