Skip to content

What is an ADR?

An Architecture Decision Record is a short document capturing one design decision: what we chose, why, and what we considered and rejected. The platform has 33 ADRs as of Phase 1; every meaningful technical decision since the project started has one.

If you’re reading the codebase and wondering why something is shaped a particular way, the answer is usually in an ADR.

Every ADR follows a four-section structure:

  • Context. What problem are we solving? What forces are at play? What constraints exist? This section establishes why the decision matters at all.
  • Decision. What did we pick? Stated in one or two sentences. No equivocation; an ADR records a commitment.
  • Consequences. What becomes easier. What becomes harder. What trade-offs we’re accepting. The honest version of “we chose X” — not just the upsides.
  • Alternatives considered. Other options, and why we didn’t pick them. The discipline here is being specific: “simpler” or “more flexible” isn’t a real reason; “saves us from running a Postgres cluster” is.

Each ADR also has a status (Proposed, Accepted, Superseded by ADR-NNNN, or Deprecated) and a date. Older ADRs sometimes link forward to newer ones that supersede or extend them.

Three reasons that compound over time:

1. Reasoning gets lost. Six months from now, someone will ask “why are we using Cloudflare D1 instead of Postgres?” The ADR has the answer. Without it, the answer is whatever the person who happens to remember says. Memories are unreliable; an ADR isn’t.

2. New contributors land faster. A new engineer reading the codebase wants to understand not just what it does but why it’s shaped this way. Code shows the what; ADRs show the why. A new hire reading the 33 ADRs in order has a clearer mental model of the system than someone who’s been rummaging through the source for a month.

3. Decisions get challenged honestly. If you can’t write an ADR for a choice, you probably haven’t thought it through. Forcing the four-section structure surfaces fuzzy reasoning. Several decisions on this platform got substantively rethought because the ADR-writing process exposed weak alternatives.

The rule, stated simply: an ADR documents a committed decision that has shaped the codebase. Two implications:

  • Don’t write speculative ADRs. Ideas under consideration go in docs/open-questions.md, not the ADR folder. An ADR represents a commitment that’s reflected in code.
  • Don’t skip non-obvious choices. If a future maintainer might ask “why didn’t we just do the obvious thing here?”, there’s an ADR worth writing. The code shouldn’t have to defend itself.

What counts as “shaping the codebase”:

  • A new package, app, or service got added (or an existing one got refactored across the trust boundary)
  • A library/framework choice that affects multiple packages
  • A protocol decision: file format, message schema, error taxonomy
  • A security decision: what’s mutable, what’s immutable, what’s validated where
  • A scaling/cost decision: choice of provider, choice of pricing tier, choice of caching layer

What doesn’t count:

  • Bug fixes
  • Refactoring within a package that doesn’t change its interface
  • Performance tuning that doesn’t affect the design
  • Routine library upgrades

Proposed — under discussion; a PR is open or the code is staged. The ADR exists so reviewers can see the design alongside the code, but the decision isn’t final.

Accepted — in effect, reflected in the repo. Most ADRs spend their life in this state.

Superseded by ADR-NNNN — replaced by a later decision. The old ADR stays in place (history matters); a forward link in the status field points to its replacement. The new ADR’s Context section explains what changed.

Deprecated — no longer in use, not replaced. Rare; usually this happens when a feature is removed entirely.

Every ADR lives at docs/adr/NNNN-short-title.md in the repo, authored as plain Markdown. The docs site mirrors them at build time (so the full index below is always in sync with the repo).

For people reading the docs, the recommended path is:

  1. Skim the full index to see the breadth
  2. Read the highlighted ADRs — six decisions that shaped the platform’s identity
  3. Click into individual ADRs when you have a “why is this like this?” question about the code

The highlights are the right place to start if you’re an engineer ramping up; the full index is the right place to come back to when something specific catches your attention.

We don’t use a tool — no adr-tools, no plugin, no generator. Just plain Markdown files following a template. The discipline is in the writing, not in the tooling. A file in the right place with the right structure is the entire system.

The build-time copy script that mirrors docs/adr/ into the docs site (apps/docs/scripts/copy-adrs.mjs) is the only automation, and it’s 70 lines of plain Node.