ADR template: Nygard, MADR and Y-statement (+ examples)
Copy-paste architecture decision record templates (Nygard, MADR 4.0, Y-statement), a repo layout with adr-tools commands, and three worked ADR examples.
An architecture decision record (ADR) is a short document that records one significant technical decision: what was decided, why, and what follows from it. This page gives you three ADR templates to copy, a repo layout, the adr-tools commands, three worked examples, and a guide to picking a format. For the background on why ADRs exist and where they fall short, see the ADR guide or the short glossary definition.
Template 1: Nygard ADR (the classic)
Michael Nygard proposed this format in Documenting Architecture Decisions (November 2011). It's five sections, and it's still the default for most teams.
# ADR-0001: [Short noun phrase, e.g. "Use Postgres as the job queue"]
## Status
Proposed | Accepted | Deprecated | Superseded by ADR-NNNN
## Context
The forces at play: technical, political, social, and project-specific.
Describe them neutrally. Write for someone joining the team in a year.
## Decision
"We will ..." in full sentences, active voice.
## Consequences
What becomes easier and what becomes harder after applying this decision.
Positive, negative, and neutral consequences all belong here.
Nygard's four statuses are Proposed, Accepted, Deprecated, and Superseded (with a reference to the replacement). Add a date line under the title; most teams do.
Template 2: MADR 4.0
MADR (Markdown Architectural Decision Records) is the most widely used structured alternative. The current major version is 4.0.0, released September 2024. It adds decision drivers, explicit options, a "Confirmation" section for how compliance will be checked, and YAML frontmatter for status and the people involved. Sections marked optional can be deleted. This is a condensed version of the official template:
---
status: proposed | rejected | accepted | deprecated | superseded by ADR-0123
date: YYYY-MM-DD
decision-makers: [names]
consulted: [subject-matter experts, two-way communication]
informed: [people kept up to date, one-way communication]
---
# {Short title, representative of solved problem and found solution}
## Context and Problem Statement
Two or three sentences, or a short story. Optionally phrase it as a question.
## Decision Drivers <!-- optional -->
* {driver 1, e.g. a force or concern}
* {driver 2}
## Considered Options
* {option 1}
* {option 2}
* {option 3}
## Decision Outcome
Chosen option: "{option 1}", because {justification}.
### Consequences <!-- optional -->
* Good, because {positive consequence}
* Bad, because {negative consequence}
### Confirmation <!-- optional -->
How compliance will be checked: code review, an architecture test, etc.
## Pros and Cons of the Options <!-- optional -->
### {option 1}
* Good, because {argument}
* Neutral, because {argument}
* Bad, because {argument}
## More Information <!-- optional -->
Links, evidence, when to revisit.
MADR's own convention is files named NNNN-title-with-dashes.md in a decisions/ folder (it suggests docs/decisions). The consulted and informed fields map loosely onto RACI-style roles; if your org uses DACI, you can rename them.
Template 3: Y-statement (one sentence)
The Y-statement comes from Olaf Zimmermann and colleagues, presented at SATURN 2012 and described in his post Y-Statements. It packs a decision into one long sentence with six parts. Use it for smaller decisions, or as the summary line at the top of a longer ADR.
In the context of <use case / component>,
facing <concern or quality requirement>,
we decided for <chosen option>
and neglected <alternatives>,
to achieve <benefits>,
accepting that <drawbacks / consequences>.
Repo layout and adr-tools
Keep ADRs next to the code they govern, so changes to them get reviewed in the same pull requests:
docs/adr/
README.md # index (can be generated)
0001-record-architecture-decisions.md
0002-use-postgres-as-the-job-queue.md
0003-version-the-public-api-in-the-url.md
0004-store-sessions-in-redis.md
Rules: four-digit zero-padded numbers, lowercase dashed titles, numbers never reused, files never deleted.
adr-tools by Nat Pryce is a small set of shell scripts that automates this (brew install adr-tools on macOS). Its default directory is doc/adr, but you can choose one at init:
# Create the directory and ADR 0001 ("Record architecture decisions")
adr init docs/adr
# New ADR, numbered automatically, opened in $VISUAL / $EDITOR
adr new Use Postgres as the job queue
# New ADR that supersedes ADR 2 (also updates ADR 2's status)
adr new -s 2 Use a managed queue service
# Link two ADRs with a custom relationship
adr link 3 Amends 1 "Amended by"
# Generate an index
adr generate toc > docs/adr/README.md
If you want something other than shell scripts, see the adr-tools comparison.
ADR in Confluence
If PMs, designers or other teams need to read ADRs, Confluence can be the better home. Use the Nygard or MADR body above, put Status, Owner, Date and Review-by in a Page Properties table, and label pages adr. The full setup, including a self-updating register, is in the Confluence decision log template. The trade-off: Confluence ADRs aren't reviewed with the code and drift out of sync more easily.
Three architecture decision record examples
These examples are illustrative, written for a fictional SaaS backend.
Example 1 (Nygard): job queue
# ADR-0002: Use Postgres as the job queue
Date: 2026-10-01
## Status
Accepted
## Context
We need background jobs for email, webhooks and report generation. Current
load is a few hundred jobs per minute. We already run Postgres with backups
and monitoring. The team is four engineers; every extra stateful service
costs on-call time.
## Decision
We will run background jobs on a Postgres-backed queue using
SELECT ... FOR UPDATE SKIP LOCKED. All new background work goes through
the shared queue module. We will revisit when sustained load passes
5k jobs/min.
## Consequences
- No new infrastructure to operate; jobs are transactional with app writes.
- Queue load competes with application queries on the same database.
- Moving to a dedicated queue later means migrating the queue module, not
every caller, as long as callers use the module.
Example 2 (MADR): API versioning
---
status: accepted
date: 2026-10-12
decision-makers: [Marco, Aisha]
consulted: [Lee (SDKs), Dana (customer success)]
informed: [all engineering]
---
# Version the public API in the URL path
## Context and Problem Statement
We're about to make the first breaking change to the public REST API.
How should clients select an API version?
## Decision Drivers
* Integrators must be able to see the version in logs and curl commands
* Our SDKs and API gateway must support it without custom work
## Considered Options
* URL path (/v1/, /v2/)
* Custom request header (Api-Version: 2)
* Date-based version header
## Decision Outcome
Chosen option: "URL path", because it is visible everywhere a request is
logged or pasted, and needs no gateway changes.
### Consequences
* Good, because support can read the version from any request log
* Bad, because the whole API moves version at once, not per endpoint
### Confirmation
An API contract test fails if a route is registered outside a /vN/ prefix.
## Pros and Cons of the Options
### Custom request header
* Good, because URLs stay stable
* Bad, because the version is invisible in most logs and pasted URLs
Example 3 (Y-statement, superseding an earlier ADR)
# ADR-0004: Store sessions in Redis
Date: 2026-10-20
Status: Accepted. Supersedes ADR-0003 (sticky sessions on the load balancer).
In the context of the web app running on multiple instances,
facing users being logged out whenever an instance is replaced,
we decided for server-side sessions stored in Redis
and neglected sticky sessions and stateless JWT sessions,
to achieve sessions that survive deploys and autoscaling,
accepting that Redis becomes a dependency of every authenticated request.
ADR-0003's status line would then read Superseded by ADR-0004, with its body left unchanged.
Which ADR template to use
| Situation | Use |
|---|---|
| Starting out, most decisions | Nygard: five sections, low friction |
| Several real options, cross-team stakes, or you want an audit trail of who was consulted | MADR 4.0 |
| Small, local decisions you'd otherwise not record at all | Y-statement |
| Big, uncertain change that needs discussion first | An RFC or design doc first, then an ADR recording the outcome |
| Product, pricing or design calls | A general decision log template rather than an ADR |
Whichever you pick, use one template per repo. Consistency matters more than the format.
Where ADRs go wrong
The template is rarely the problem. Two things are. First, capture: most architectural decisions are made in a PR thread or a Slack huddle, and nobody leaves the conversation to write the ADR. Second, reading: an ADR sits in a folder until someone thinks to look, and the person (or AI coding agent) about to violate it usually doesn't know it exists. That's decision drift.
Lockstep is built for both gaps. It drafts decision records from Slack, Jira and Confluence for the owner to approve in one click, briefs engineers and coding agents on approved decisions via MCP, and its PR check flags changes that may conflict with them. Your ADR folder can stay exactly as it is.
Frequently asked questions
- What is the standard ADR template?
- The closest thing to a standard is Michael Nygard's 2011 format: Title, Status, Context, Decision, Consequences. MADR (Markdown Architectural Decision Records) extends it with decision drivers, considered options, and pros and cons; its current major version is 4.0.0, released September 2024.
- Where should ADRs be stored?
- Usually in the code repository, as numbered Markdown files such as docs/adr/0001-record-architecture-decisions.md, so they are reviewed in pull requests alongside the code they govern. Confluence or Notion makes sense when non-engineers need to read and comment on them.
- Can you edit an ADR after it is accepted?
- Fix typos and add links, but don't change the decision. If the decision changes, write a new ADR that supersedes the old one and set the old one's status to 'Superseded by ADR-NNNN'. The history is the point.
- How long should an ADR be?
- Nygard suggested one or two pages. Many good ADRs are shorter. If it needs more than two pages, the exploration probably belongs in an RFC or design doc, with the ADR recording the outcome.
Keep reading