Skip to content

Architecture decision record examples: 10 real ADRs + template

Scribelet Team
20 min read

You're new on a team and you find a folder called doc/adr/. Inside: 47 numbered Markdown files, the oldest from 2019, the newest from 2022. The eighth one explains, in confident prose, why the team picked PostgreSQL over MongoDB. The current code, you find out the next morning, runs on DynamoDB.

Nobody superseded the ADR. Nobody deleted it. It just sits there, looking authoritative, contradicting the codebase silently.

This is the state of most architecture decision record directories in production. Tutorials show clean Nygard-style templates and one polished example. Real repositories show supersession links nobody updated, ADRs orphaned by authors who left two years ago, and entries marked "Accepted" that the team quietly stopped following. The same rot lands on every artifact a repository carries, down to the issue template that still lists a platform the project dropped support for two releases back.

This article gives you an architecture decision record template you can copy today, two fully worked ADR examples including the superseded pair almost nobody publishes, and 10 real decision records from open-source projects worth studying. Then it names the patterns that separate the alive from the rotted. The format is the easy part. The maintenance discipline is what makes a decision log worth reading.

What is an architecture decision record?

An architecture decision record (ADR) is a short Markdown document, usually one page, that captures a single architectural decision: the context that forced the choice (often the org structure itself, per Conway's law), the options considered, the choice made, and the consequences. ADRs live in the source repository alongside the code, are numbered sequentially, and are never edited after acceptance. To change a decision, you write a new ADR that supersedes the old one.

Michael Nygard popularized the format in 2011. The concept of decision logs predates him; the lightweight Markdown form is his contribution. Today the term covers a family of formats: MADR, Y-statement, Tyree-Akerman, arc42, and the loose conventions most teams build for themselves.

An ADR is deliberately narrower than a software design document. A design doc proposes an entire system before it exists and stops being true at merge; an ADR records one choice and stays valid long after the system around it has been rewritten. That difference in scope is why the "alternatives considered" section of a retiring design doc belongs in an ADR rather than the wiki. It is also why a recorded decision is the cheapest guard against a rejected feature quietly creeping back: the reasoning survives the person who made the call.

Architecture decision record lifecycle diagram showing transitions from Proposed to Accepted or Rejected, and from Accepted to Superseded with bidirectional cross-links to the new ADR

Architecture decision record template

Most ADR templates you'll find stop at Context, Decision, and Consequences. Those three fields record what you decided. They record nothing about when the decision stops being true, which is the failure this whole article is about.

The template below adds four maintenance fields to the standard Nygard structure. Copy it as doc/adr/NNNN-short-title.md.

# ADR-014: Use Stripe Billing for subscription invoicing
 
**Status:** Accepted
**Date:** 2026-03-11
**Owner:** D. Lee
**Last verified:** 2026-07-02 by D. Lee, method: re-read Stripe pricing page and re-ran billing integration tests
**External dependencies:** Stripe Billing API v2, Stripe pricing tier (0.5% on recurring), EU SCA regulations
**Drift triggers:** Stripe deprecates the v2 webhook signature, Stripe raises the recurring fee above 0.8%, our MRR exceeds $2M (renegotiation threshold), we need invoicing in a country Stripe does not serve
 
## Context
 
We bill roughly 4,000 monthly subscriptions across 14 currencies. Our
current hand-rolled invoicing runs on a cron job that reconciles against
Postgres, and it has produced three billing incidents in two quarters.
We need dunning, proration, tax handling, and SCA compliance, none of
which we want to own.
 
## Decision
 
We will use Stripe Billing for all recurring subscription invoicing.
Our system remains the source of truth for entitlement; Stripe is the
source of truth for money.
 
## Alternatives considered
 
- **Chargebee:** Better multi-gateway support, but adds a second vendor
  on top of Stripe, which we already use for payments.
- **Keep building in-house:** Rejected. Tax and SCA compliance alone is
  a standing headcount cost we cannot justify at our size.
 
## Consequences
 
- **Positive:** Dunning, proration, and SCA stop being our problem.
- **Positive:** One vendor for payments and billing, one reconciliation path.
- **Negative:** 0.5% of recurring revenue leaves as vendor fee.
- **Negative:** Entitlement logic now spans two systems and must stay in sync.
- **Negative:** Migrating off Stripe later means migrating billing history.

Two fields do most of the work. Last verified is deliberately separate from Date: every tool already shows you when a file was last edited, and last edited tells you nothing about whether anyone checked that the content is still true. Drift triggers are written while you still remember which parts of the world the decision leans on. Reconstructing them a year later is guesswork, which is exactly the situation Chesterton's fence describes: someone finds the decision, can't tell if the reasoning still holds, and has to choose between trusting it blind and tearing it out blind.

Copy-paste ADR templates: MADR, minimal Nygard, and Y-statement

The template above is the one to adopt if you want maintenance built in. If you only need a standard starting point to drop into doc/adr/, here are the three formats teams reach for most, shortest first. Copy any of them and add the two maintenance lines afterward.

Minimal Nygard is the smallest record that still captures the "why":

# ADR-NNNN: <short title of the decision>
 
**Status:** Proposed | Accepted | Superseded by ADR-XXXX
**Date:** YYYY-MM-DD
 
## Context
<the forces and constraints that make this decision necessary>
 
## Decision
<the choice, in one or two sentences, and why it wins>
 
## Consequences
<what gets easier, what gets harder, what you now have to live with>

MADR (Markdown Any Decision Records) adds the alternatives and the drivers to the page, so the record shows the options you weighed, not only the one you picked:

# <short title of the problem and the chosen solution>
 
**Status:** proposed | accepted | rejected | superseded
**Date:** YYYY-MM-DD when the decision was last updated
 
## Context and problem statement
<what is the motivation, what is the disagreement>
 
## Decision drivers
- <driver 1: a constraint or a non-functional requirement>
- <driver 2: cost, team skill, tech-stack fit>
 
## Considered options
- <option 1>
- <option 2>
 
## Decision outcome
Chosen: "<option 1>", because <the justification and the trade-offs you accepted>.
 
### Consequences
- Good, because <positive impact>
- Bad, because <negative impact>

The Y-statement compresses the whole record into one sentence, for a decision small enough to live in a pull request or a chat thread:

In the context of <use case>, facing <concern>, we decided <option>,
to achieve <quality>, accepting <downside>.

Whichever you copy, paste the Last verified and Drift triggers lines from the maintenance template above underneath it. The format decides how you write the decision down; those two fields are the only part of any ADR template that tells you when to stop trusting the decision.

What a superseded architecture decision record looks like

The single most common defect in real ADR directories is a decision that was reversed without anyone writing it down. The old record still reads "Accepted." Here is the other half of the pair, the record that retires the one above.

# ADR-027: Move subscription invoicing to Paddle (merchant of record)
 
**Status:** Accepted
**Supersedes:** ADR-014 (Use Stripe Billing for subscription invoicing)
**Date:** 2026-06-24
**Owner:** D. Lee
**Last verified:** 2026-06-24 by D. Lee, method: signed contract, ran parallel billing for one cycle
**External dependencies:** Paddle merchant-of-record agreement, EU and UK VAT registration thresholds
**Drift triggers:** Paddle's fee exceeds 5%, we incorporate an entity in the EU (which removes the MOR advantage), Paddle drops support for a currency we sell in
 
## Context
 
ADR-014 chose Stripe Billing and was correct for the constraints of the
time. One of its named drift triggers fired: expanding into the EU put
us over the VAT registration threshold in four countries. Stripe Billing
leaves us as the merchant of record, so that filing burden is ours.
 
## Decision
 
We will move recurring invoicing to Paddle and operate under its
merchant-of-record model. Stripe remains in place for one-off payments.
 
## Consequences
 
- **Positive:** Paddle files VAT as merchant of record. Four registrations avoided.
- **Negative:** Paddle's effective rate is roughly 5%, against Stripe's 0.5% plus our filing cost.
- **Negative:** Less control over the checkout surface and the dunning schedule.

Notice what the pair gives a reader that a single record cannot. ADR-014 was not wrong; a condition it named in advance came true. The new engineer reading both learns the current state and the reasoning that moved it, in about ninety seconds. Then update ADR-014's header to **Status:** Superseded by ADR-027 so the link points both ways. Most teams update one side and forget the other, which is how a reversed decision keeps looking authoritative.

ADR formats: Nygard, MADR, and Y-statement compared

The template above is Nygard's structure, extended. It is the most common ADR format, but it is not the only one, and the right format depends on how much structure your team will actually keep current. Four formats cover almost every architecture decision record you will meet in the wild.

FormatWhat it addsBest for
NygardTitle, Status, Context, Decision, Consequences. The base.The default. Teams that want the least structure that still records the "why".
MADR (Markdown Any Decision Records)Considered Options with per-option pros and cons, plus Decision Drivers and a Decision Outcome.Teams that want the alternatives weighed on the page, not just named.
Y-statementOne sentence: "In the context of X, facing Y, we decided Z, to achieve W, accepting V".Recording a decision inline in a pull request or a chat thread when a full file is overkill.
Tyree-AkermanAssumptions, Constraints, Positions, Argument, Implications, Related decisions.Regulated or high-stakes systems where the full argument has to be auditable.

Pick the lightest format your team will keep current. A Nygard record somebody updates beats a Tyree-Akerman record nobody re-reads. Whichever you choose, the one addition worth making is the maintenance block from the template above: the format decides how you write the decision down, but nothing in any of these standard formats tells you when the decision stops being true.

For a decision small enough to live in a single sentence, the Y-statement is the whole record:

In the context of subscription invoicing, facing EU VAT registration
thresholds, we decided to move to Paddle as merchant of record, to avoid
filing VAT in four countries, accepting a fee near 5% against Stripe's 0.5%.

That is the same ADR-027 decision from the superseded pair above, compressed to one line. Use the long form when the alternatives need room to breathe; use the Y-statement when the decision is real but the argument is short. Both are architecture decision records; they differ only in how much of the reasoning survives in writing.

10 architecture decision record examples worth studying

Every link below was live in April 2026. By the time you read this, some directories may have moved or stopped being updated. That is the point of the article. ADRs decay along with everything else.

1. MADR project (the format documenting itself)

The Markdown Any Decision Records (MADR) project documents its own format using its own format. Each ADR in the repository follows the template the project recommends. It's the cleanest example of an ADR format eating its own dog food, and a good place to start if you want to see what "good" looks like before customizing.

Worth copying: the dated decision filename pattern (YYYYMMDD-decision-title.md) and the explicit "Considered Options" section that lists alternatives with concrete pros and cons.

2. Cosmos SDK

The Cosmos SDK keeps its ADRs under docs/architecture/. Sixty-plus numbered records cover everything from gas accounting to module structure. The supersession discipline here is unusually strict: when an ADR is replaced, the old file gets a Status: Superseded by ADR-NNN header at the top, and the new ADR cross-references back. Reading the directory in chronological order is a tour of how the architecture evolved over five years.

Worth copying: bidirectional supersession links. Most projects only update one side.

3. Spotify Backstage

Backstage, Spotify's developer portal platform, publishes its architecture decisions inside its docs tree. The notable pattern is linking each ADR to the pull request that implemented it. You can read the decision, then click through to the diff that put it into the codebase. This collapses the gap between "we decided X" and "X is actually how the system works now," which is one of the main ways ADRs go stale.

4. EdgeX Foundry

EdgeX Foundry, an open-source IoT platform under the Linux Foundation, publishes its ADRs in edgex-docs. The template borrows from arc42 and includes a dedicated "Risks and Technical Debt" section that most ADR formats leave out. Useful precedent for any team operating in a regulated or mission-critical context.

5. adr-tools (Nat Pryce)

Nat Pryce's adr-tools is a command-line utility for managing ADRs in git. The tool's own ADRs live in doc/adr/ in the same repository. The directory is small (under 10 records), but the early entries explain why the tool exists and the CLI conventions it picked. You can read the entire decision history in 20 minutes; there is no faster way to internalize the format.

6. Kubernetes Enhancement Proposals (KEPs)

Strictly speaking, KEPs aren't ADRs. They're heavier process documents with explicit lifecycle states (provisional, implementable, implemented, deferred, rejected, withdrawn, replaced). But the lifecycle model is exactly what teams whose ADRs go stale need to copy. Every KEP has an owner, a sponsor SIG, and a graduation criteria checklist. Drift is hard without somebody actively neglecting an assigned record.

7. Apache Kafka Improvement Proposals (KIPs)

Kafka's KIPs predate the modern ADR movement and are heavier still. Over a thousand KIPs have been filed across a decade. Several hundred have been formally superseded. For any team that worries supersession discipline cannot scale, the Kafka KIP index is the rebuttal.

8. React RFCs

The React RFCs repository sits between an ADR and a design document. The RFCs are public, debated in the open through GitHub discussions, and remain useful long after a decision is made because the discussion thread captures dissent and alternatives the final decision did not adopt. ADRs are usually written in private; React's are written in public, which makes them an unusually rich teaching example.

Capturing dissent is also the test for the document that comes before the decision. A plan earns its review by making claims a reviewer can disagree with, and the alternatives it rejects are exactly what the ADR inherits once the argument is settled.

Joel Parker Henderson's architecture-decision-record repository is the most-starred ADR resource on GitHub (15.7k stars at last count) and the place most teams find their first template. It's a gallery of formats rather than a maintained ADR log: useful as a comparison tool, less useful as a study in maintenance discipline.

10. arc42

arc42 is a documentation methodology that integrates ADRs as one component of a broader architecture documentation structure. Worth studying if you want decision records that link cleanly to other architecture artifacts (quality scenarios, system context, building blocks) rather than living in isolation. The cost is more upfront structure; the benefit is that an ADR is never an orphan document.

Three patterns that separate living architecture decision records from dead ones

After reading enough ADR directories, the pattern of decay becomes predictable. Three signals consistently separate the directories teams still trust from the ones they have learned to ignore.

Side-by-side comparison of a decayed ADR with no owner, no supersession link, and no drift triggers, alongside the same record rebuilt with the maintenance fields a healthy decision log uses

Explicit ownership on every record

The healthiest ADR directories name a person, not "the team." When the inevitable question comes up two years later ("Why did we pick gRPC?"), an unowned ADR forces the new team into archaeology. An ADR with Owner: D. Lee next to its status field gives them a starting point. Cosmos SDK does this. Backstage does this. The directories that don't tend to drift.

The Nygard convention is to mark an old ADR Superseded by ADR-NNN and add a Supersedes ADR-MMM reference on the new one. Most teams update one side and forget the other. Reading old ADRs without forward references is one of the fastest ways to act on a decision the team has already reversed. The Cosmos SDK convention of always updating both files is small, mechanical, and one of the clearest signals of a maintained directory.

Named drift triggers

A decision based on external constraints (vendor pricing, framework version, regulatory requirement) decays the moment those constraints change. The strongest ADRs name the trigger explicitly: "Reconsider this decision if Stripe deprecates the v2 webhook signature, AWS publishes a managed alternative, or transaction volume exceeds 10M per month." Without a named trigger, an ADR has no condition under which to expire. With one, anyone reviewing it knows what to look for. The technique transfers directly to operational docs, where a runbook that tells you when it's wrong beats one that gets skimmed every quarter.

How architecture decision records go stale

Three failure modes show up across every directory of more than 30 ADRs.

The first is orphaned ownership. An author leaves the company. Nobody is assigned the records they wrote. The decisions remain "Accepted" forever even after the codebase moves on. This is the most common form of decay and the most preventable: assign new owners during offboarding the way you reassign open pull requests.

The second is missing supersession. A team makes a new decision in a Slack thread, ships it, and never writes the corresponding ADR. The old ADR is silently wrong. Six months later, a new engineer reads it and wastes an afternoon implementing the deprecated approach. The fix is procedural rather than technical: making "did this need a new ADR?" a checklist item in code review. It is one of the few checklist items that earns its place, because no machine can answer it; what to delete from your pull request template covers the ones that don't.

The third, hardest to catch, is hidden external dependency drift. The ADR was written when AWS Lambda's cold-start penalty was a multi-second concern. AWS has since published Provisioned Concurrency and runtime improvements that bring typical cold starts well under a second. The ADR, which used cold-start penalty as a major reason to avoid Lambda, is now built on outdated cost-benefit assumptions. The decision may still be right, but the rationale has rotted. This is the kind of drift that hand audits rarely catch. It's the engineering-specific case of the broader knowledge decay problem and the central pattern in outdated documentation of every kind.

Maintenance patterns worth copying

Five patterns appear across the well-maintained examples above. Each takes minutes to add and pays back over years.

  1. A Last verified: date in every ADR header, separate from the original Date: field. Tells future readers when the rationale was last sanity-checked, not just when the decision was made. It is the same distinction that decides whether internal documentation stays trustworthy: every tool shows you last edited, and last edited says nothing about accuracy.
  2. An Owner: field with a single name. "The team" is not an owner; nobody on a team will feel personally responsible for a record assigned to all of them.
  3. An External dependencies: block listing every vendor, framework version, or regulatory document the decision depends on. Makes drift triggers explicit instead of implied.
  4. A scheduled review cadence. Quarterly for ADRs that touch external APIs; annually for ADRs about internal architecture. Add it to the same calendar as your dependency updates.
  5. Supersession-only edits. Once an ADR is accepted, the only acceptable change is a new ADR that supersedes it (with both files cross-linking). Silent edits hide history; they don't preserve it.

Tools for managing architecture decision records

You do not need tooling to keep ADRs. A doc/adr/ folder and a numbering convention is enough, and several of the examples above run exactly that way. But three small tools remove the friction that makes teams stop writing records at all.

  • adr-tools (Nat Pryce's CLI, linked in example 5 above): adr new "Use Paddle for invoicing" creates the next-numbered file from a template and adr link wires up a supersession. Shell-based, no runtime, works anywhere git does.
  • Log4brains: turns a doc/adr/ directory into a searchable static site with a timeline view, so the decision log is browsable outside the repository. Useful once a directory passes 30 records and reading raw files gets slow.
  • MADR tooling (adr-manager and the MADR CLI): scaffolds and edits records in the MADR format, for teams that adopt its heavier structure and want the fields filled in consistently.

Every one of these solves creation, numbering, and linking. None of them solves maintenance, which is the failure this article keeps returning to: a tool can generate a record and cross-link a supersession, but only a person, or an agent watching the repository, notices that a two-year-old decision has quietly stopped matching the code.

AI agents as fitness functions for architecture decision records

Joel Parker Henderson's repository has a section on "fitness functions for decisions as code": automated checks that verify a decision is still being followed in the codebase. The original idea is structural; you write a unit test that asserts an architectural rule (ArchUnit for Java, dependency-cruiser for JavaScript, similar tools for other stacks).

The pattern extends naturally to maintenance. An ADR's external assumptions (a vendor pricing tier, a framework version, a regulatory line) can be background-checked. Scribelet's verification feature does this for Markdown notes generally: background agents periodically search the web, compare findings to what you wrote, and surface a diff when they drift apart. Applied to an ADR, an agent can flag when current AWS Lambda documentation contradicts the cold-start numbers cited in your three-year-old serverless decision. The same shift shows up one step earlier, in the move to writing a spec your agent builds from rather than prompting and correcting after the fact.

The harder case is ADRs that describe your own system rather than external dependencies. Web search cannot see whether your code still matches the decision; only the repository can. Scribelet's GitHub connector plugs that gap by letting verification search a connected repository through GitHub's Code Search API. The PostgreSQL ADR from this article's opening is exactly the case it was built for: the moment somebody pushes DynamoDB code that contradicts the record, the agent has both halves in front of it.

The agent doesn't make the decision. It surfaces the drift. A human still owns the call to supersede the ADR or update the rationale. If you use Scribelet for this on a Pro plan, you can route the verification through your own AI provider via BYOK (Bring Your Own Key): your data goes to OpenAI, Anthropic, or Gemini directly, with your key encrypted at rest.

Frequently asked questions

What's the difference between an ADR and an RFC?

An RFC (Request for Comments) is a proposal under discussion; an ADR is a decision after discussion has closed. RFCs are debated, edited, and may be withdrawn. ADRs are accepted or rejected, then frozen. Some projects (React, Rust) use RFCs because they want public deliberation as part of the artifact. Most internal teams use ADRs because they want a clear closed record.

How long should an architecture decision record be?

One page, ideally. Martin Fowler's recommendation is to follow the inverted-pyramid style of news writing: the decision and rationale go first, supporting detail goes later. If a decision needs more than a page to explain, link to a separate design document and keep the ADR itself summary-form.

Who should write the ADR?

Whoever is closest to the decision: the engineer who proposed it or the architect who made the call. Not a designated documentation owner separated from the work. ADRs written by people removed from the decision read as procedure and tend to omit the rationale that makes the record useful later.

Should accepted ADRs be edited or superseded?

Superseded. Once accepted, an ADR is part of the historical record. Editing it loses the trail of what the team actually believed at the time. Supersession preserves both the original decision and the reason it changed.

Where should architecture decision records live?

In the source repository, alongside the code they describe. The conventional location is doc/adr/ or docs/architecture/. ADRs that span multiple repositories (cross-team or cross-product decisions) live in a shared docs repo or wiki. Everyone who looks at the affected code should be one click away from the relevant ADRs.

What is the standard ADR format?

There is no single standard, but Michael Nygard's format (Title, Status, Context, Decision, Consequences) is the de facto default and the base for most others. MADR extends it with explicit options and decision drivers; the Y-statement compresses a decision to one sentence; Tyree-Akerman adds a full auditable argument. Pick the lightest one your team will keep current, then add a maintenance block so the record carries an expiry condition. The same one-line record settles the trivial rules too, the naming convention or the indent width that reignites the same argument every few months once the reason behind it is forgotten.

What tools help manage ADRs?

Most teams need nothing beyond a doc/adr/ folder and a numbering convention. adr-tools (a shell CLI) automates creation and supersession links; Log4brains renders a directory into a browsable static site; MADR's tooling scaffolds records in that format. All three handle creation and numbering. None handles the harder problem of noticing when an accepted decision no longer matches the code.

Conclusion

The format is the easy part. Anyone can copy a Nygard template and write three good ADRs in an afternoon. The directories that still serve their team five years later have something the template alone does not provide: an owner on every record, supersession links that point both ways, named drift triggers, and a review cadence somebody actually keeps.

The decision is half the work. Watching it for drift is the other half.

An ADR is the format for architectural decisions specifically. For the everyday calls a team makes outside the codebase, the same discipline runs through a general decision-making framework and a written decision record: pick the method that fits the decision, then keep the reasoning where it can be re-checked.

Start writing with background verification. Try Scribelet free.

Share this article

We use cookies for analytics to improve your experience. Learn more