// starters/architecture/adr

architecture decision records (adr)

The format for writing down decisions that need to outlast the conversation. Short, structured, numbered. Catches the "why did we do it this way?" gap that hits every project six months in.

last fed 28 may 20261047 words · 5 min read
// when to use this starter

Fork this when you're making a decision the team (or the next AI session) will need to revisit. Use it for framework choice, infra change, schema-shaping pattern — anything where reversing the decision is expensive. Don't use it for routine refactors, bug fixes, or anything obvious from the diff.

architecturedecisionsdocumentationadrlineage

Architecture decision records

A sourdough starter for the decisions that need to survive between sessions. ADRs are short numbered documents — one per non-obvious decision, written at the time the decision is made, never deleted (they get superseded, not removed).

The format is older than AI coding (Michael Nygard wrote about it in 2011) but it pairs naturally with AI agents: the agent reads the ADR set on session start and inherits the project's accumulated reasoning. Without ADRs, every session re-decides things you've already decided.


When to write an ADR

Write one when:

  • The decision is expensive to reverse. Database choice, auth library, deployment target, API shape.
  • Multiple reasonable options existed. "I chose X over Y because…" is ADR-shaped.
  • The decision will look weird later. "Why is auth in middleware instead of per-route?" — answer it once, in the ADR, instead of every session.
  • The decision binds future decisions. "We're going with Supabase" affects every later "how do we store X?" decision.

Don't write one when:

  • It's a one-way door but obvious (e.g. "we'll use TypeScript"). No alternatives were seriously considered.
  • It's reversible cheaply (e.g. "we'll cache for 5 minutes"). Try it; change it if wrong.
  • It's task-shaped, not decision-shaped (e.g. "implement the login flow"). That's a ticket, not an ADR.

File layout

docs/adr/
├── README.md                    ← index + how to write one
├── 0001-record-architecture-decisions.md
├── 0002-use-{thing}.md
├── 0003-{kebab-title}.md
└── ...

Numeric prefix, zero-padded to 4 digits. Sequential, never reused. Kebab-case title that summarises the decision in 5-7 words.


ADR template

# ADR-NNNN: {short imperative title}

**Status:** Proposed | Accepted | Deprecated | Superseded by ADR-MMMM
**Date:** YYYY-MM-DD
**Deciders:** {names — usually one, sometimes two}

## Context

What's the situation forcing this decision? Two to four paragraphs.
Include: the constraint, the trigger, what was already true that made
this come up now. Avoid history that isn't load-bearing.

## Decision

What did we decide. One sentence at the top is ideal — then the
sub-decisions or sub-rules, often as a numbered list or sub-headings.

## Consequences

What changes because of this. Both wanted and unwanted. List the
follow-on work this decision creates, the constraints it imposes on
future decisions, the tradeoffs accepted.

## Alternatives considered

What else was on the table. One short paragraph per alternative,
ending with why it was rejected. This is the section future-you will
read most often when revisiting the decision.

## Open questions

Things the decision deferred. Either answer here, or note explicitly
that they're parked. Don't pretend everything's settled.

Status lifecycle

  • Proposed — drafted but not yet accepted. Sometimes skipped for solo projects (you propose and accept in the same sitting).
  • Accepted — the decision is in force. This is the default state for most ADRs in a healthy repo.
  • Deprecated — the decision still describes what's there, but the team would no longer make it the same way. Leave it; mark it deprecated.
  • Superseded by ADR-MMMM — a later ADR replaces this one. Both files survive; the lineage is the audit trail.

Never delete an ADR. Even when it's wrong, even when it's superseded. The archive is the audit trail of how thinking evolved.


Supersession is the right move when…

A decision changes meaningfully and the new decision has its own rationale worth recording.

  • Don't supersede for minor amendments. Add an "Amended YYYY-MM-DD" note to the existing ADR's status line.
  • Don't supersede silently. The new ADR's status line includes "Supersedes ADR-MMMM"; the old ADR's status line gets updated to "Superseded by ADR-NNNN".
  • Don't write the supersession in spite. The point is the lineage, not a takedown of the past decision.

What "good" looks like

  • Short. Most ADRs are 200-600 words. If yours is 2000, you're documenting the implementation; pull that out into a spec.
  • Specific. Cite actual constraints, actual numbers, actual library names. Generic ADRs aren't load-bearing.
  • Honest about tradeoffs. Every decision has a downside. Name it.
  • Written at the decision time, not after. Retrospective ADRs lose the alternatives section because you've already forgotten what you considered.

Example shape

# ADR-0017: Pricing model + payment scaffold

Status: Accepted — 2026-05-21
Date: 2026-05-20 → 2026-05-21
Deciders: Lewis

## Context
Payment needs to be ready when we need it. Designing the Stripe
scaffold forced a prior question — keep the marketplace per-tool
model, collapse to single tier, or something else?

## Decision
Keep per-tool + bundles + all-access, with auto-upgrade caps so a
user can never overpay…

## Consequences
- Entitlement model becomes computed-from-active-subs instead of
  pro-flag boolean
- TOOL_PRICE_PENCE + BUNDLES become live SKUs
- …

## Alternatives considered
- **Single all-access tier (£25)** — simpler Stripe scaffold, but
  loses optionality for users who want one tool. Auto-upgrade caps
  neutralise the friction objection, so the choice has no downside.
- **No bundles, just per-tool + all-access** — bundles are a useful
  middle option for users with specific needs (e.g. brand & ux). The
  ~30% bundle discount makes them genuine value, not just marketing.

Index file

A docs/adr/README.md lists every ADR with its current status. Worth maintaining for human readers; the AI gets it from the directory listing anyway.

# Architecture decision records

- [ADR-0001](./0001-...) — Three-layer architecture (Accepted)
- [ADR-0002](./0002-...) — Supabase for auth + data (Accepted)
- [ADR-0003](./0003-...) — Per-tool isolation via Workers (Accepted)
- [ADR-0017](./0017-pricing-model-and-payment-scaffold.md) — Pricing model (Accepted, partially superseded by ADR-0018)
- [ADR-0018](./0018-audit-suite-replaces-bundles.md) — Audit Suite replaces bundles (Accepted, supersedes ADR-0017 §4)

How to feed this starter

Add to it when:

  • You discover a category of decision worth ADR'ing that wasn't covered ("ADRs for prompt strategy", "ADRs for accessibility commitments").
  • A status-lifecycle edge case comes up that needs documenting ("what happens when an ADR is reversed — do we supersede with a 'revert' ADR, or amend the original?").

Remove from it when:

  • A convention turns out to be wrong (e.g. you started writing 2000-word ADRs and they're working — re-document what "good" looks like for your project).

Companion starters