# Decision records

> An architecture decision record is a short document capturing one decision, its context and its consequences, kept in the repo beside the code

Code shows what was decided. It rarely shows why, or what else was on the table.
Those reasons end up in someone's head, a chat log or a closed pull request, and
an agent starting a fresh session can read none of them. A decision record puts
them in the repo.

## Definition

Martin Fowler defines an architecture decision record (ADR) as "a short document
that captures and explains a single decision relevant to a product or ecosystem"
([Architecture Decision Record](https://martinfowler.com/bliki/ArchitectureDecisionRecord.html),
2026). The form comes from Michael Nygard's
[Documenting Architecture Decisions](https://cognitect.com/blog/2011/11/15/documenting-architecture-decisions)
(2011), which gives each record five parts:

- **title**: a numbered noun phrase naming the decision
- **status**: proposed, accepted, deprecated or superseded
- **context**: the forces in play, including what's already fixed
- **decision**: what was chosen, in full sentences
- **consequences**: what follows from it, including what gets harder

Most templates since add the options considered. Fowler also suggests a
confidence level, and what change in circumstances should prompt a second look.

## An example

A record for a decision most final projects have to make:

```md
# 0002. Store data in SQLite on the Fly volume

Status: accepted

## Context

The app runs on one small Fly machine with one volume, as fly.toml fixes.
Messages and rooms must survive a redeploy. Expected load is one class.

## Options

- SQLite on the volume: no second service, and a backup is a file copy. Only one
  machine can write to it.
- Hosted Postgres: survives scaling out, but it's a second service to run, pay
  for and connect to.
- Server memory: the least code, and lost at every restart and deploy.

## Decision

SQLite on the volume, through the framework's ORM, with migrations applied when
the server boots.

## Consequences

The app can't run on a second machine without moving its data. Migrations must
run at boot, because Fly's release_command machine has no volume. Moving to
Postgres later means a data export and a record superseding this one.
```

Give the consequences the most care. The next person, or session, to touch the
code needs to know what the choice ruled out, and a record that lists only
benefits won't tell them.

## How they're kept

- **one file per decision**, numbered in sequence: Fowler's example is
  `doc/adr/0001-htmx-for-active-web-pages.md`
- **in the repo it applies to**, so it's versioned and reviewed with the code it
  explains
- **never edited once accepted**: a changed mind is a new record, and the old
  one's status becomes superseded, with a link to its replacement
- **proposed first** when you want it reviewed, by your pod, a tutor or an agent
  arguing the other side

[adr-tools](https://github.com/npryce/adr-tools) adds `adr new` and handles the
numbering and superseding links.
[Backlog.md](https://github.com/MrLesk/Backlog.md) has a built-in
`backlog decision create`, which writes to `backlog/decisions/`.

## What gets one

A decision that is expensive to reverse, or that someone will ask about later.
In a final project that's the stack, what counts as a person, what persists and
for how long, and how a change reaches everyone else. A library you could swap
out in an afternoon, or a UI tweak, doesn't need one; the commit message is
enough.

The [final project](https://comp.anu.edu.au/courses/comp4020-agentic-coding-studio/assessments/final-project/#what-you-submit) suggests them
for the stack case in `PROCESS.md`, which can link to a record rather than
restate it, and [All at once](https://comp.anu.edu.au/courses/comp4020-agentic-coding-studio/crits/09-all-at-once/) asks you to write one
down.

## With an agent

Records help at two points in a session.

**Before the decision**, ask for options rather than an answer. An agent asked
to "add a database" picks one and builds it, and the choice is buried in the
diff. Asked for options, it lays out trade-offs you can judge:

> lay out three options for where this app stores rooms and messages, with what
> each costs on one Fly machine. Don't pick one and don't write code yet

For a choice that depends on what you want, such as the stack, have it ask the
questions instead:

> read my README, then quiz me one question at a time about what this app needs:
> how many people at once, what has to persist, how fast updates travel. Give
> each option's pros and cons. Don't recommend a stack until I've answered

Then have it draft the record for the one you choose, with the options you ruled
out, and check that the consequences say what gets harder.

**After the decision**, point `CLAUDE.md` at the records, so a fresh session
reads them before it proposes something they already rule out:

```md
## Decisions

Architecture decisions live in `doc/adr/`, one numbered file each. Read them
before proposing a change to the stack, storage or data model. To change one,
write a new record that supersedes it.
```

## Further reading

- [Nygard (2011)](https://cognitect.com/blog/2011/11/15/documenting-architecture-decisions):
  the original post and format, and still the shortest explanation
- [Fowler (2026)](https://martinfowler.com/bliki/ArchitectureDecisionRecord.html):
  status, superseding, confidence and where records live
- [adr.github.io](https://adr.github.io/): templates, including
  [MADR](https://adr.github.io/madr/), and a list of tools
- [joelparkerhenderson/architecture-decision-record](https://github.com/joelparkerhenderson/architecture-decision-record):
  many templates and worked examples
