Topic: when to retire an ADR

When to Retire an ADR — Deprecation, Supersession, and the Never-Delete Rule

Most ADR guidance covers creation. The harder question comes two or three years later: a service was sunset, a team reorganized, a framework was deprecated upstream, and the ADRs that governed it are now archaeology. Three paths: supersede (decision replaced by a named new ADR), deprecate (decision no longer operative, no single successor), or delete (almost never right). Getting this wrong in the "just delete it" direction corrupts the audit trail — it removes the evidence that the decision existed, which is precisely what the ADR practice is designed to preserve.

TL;DR

When the Decision section became false and a new ADR explicitly replaced it: supersede (two-file atomic PR, bidirectional pointers). When the Context became void — the component was removed, the area dissolved — but there's no named replacement decision: deprecate (one file, one-sentence reason in Notes, Status → Deprecated). When a Proposed ADR's PR was closed without merging: the only justified deletion. In all other cases, the ADR stays — stale archaeology is exactly what the ADR practice is for.

Three paths for an obsolete ADR

When an ADR no longer reflects current practice, there are exactly three correct responses. Two of them preserve the audit trail; one destroys it. The right choice depends on why the ADR became obsolete — specifically, whether it was the Decision section or the Context section that became untrue.

Path Condition Operation Files touched CI check Right when
Superseded A new ADR explicitly reversed the choice — the Decision section is now factually false Set old ADR Status: Superseded + Superseded-by pointer; new ADR gets Supersedes pointer Two files in one atomic PR CI supersession integrity job verifies both pointers resolve to existing files The team chose option B over option A, and option B is documented in a named ADR
Deprecated The decision's context is void — the component no longer exists, the area dissolved, no replacement decision was made Set Status: Deprecated; add Notes entry with date and one-sentence reason; optionally add Deprecated-by pointer One file only No CI file-existence check on Deprecated-by (pointer is to a PR, ticket, or URL, not another ADR) The whole architectural area went away and there is no new ADR to name as successor
Deleted A Proposed ADR whose PR was closed without merging — it never reached the canonical branch Close the draft PR; no commit needed. If the file accidentally landed on the default branch before the PR was closed, a cleanup commit is acceptable One file removed; no other ADR references it No CI check can catch an invalid deletion — the file simply disappears The ADR never became Accepted, never governed any implementation decision, and no other ADR cross-references it

The core conceptual distinction: Superseded means the Decision section is now false — the team made option A; they now make option B, and the new ADR naming option B exists. Deprecated means the Context section is now void — the architectural question the ADR was answering no longer applies, because the system it governed is gone.

A concrete pair of examples makes this tangible. An ADR titled "Use Redis for job queue backend" becomes Superseded when the team writes "Switch to Valkey for job queue backend" and explicitly reverses the choice: the Decision section of the old ADR now describes an option the team explicitly rejected. The same ADR becomes Deprecated if the team removes the job queue layer entirely in favor of Temporal (a managed workflow engine) and never writes a "use Temporal" ADR because Temporal was a vendor procurement decision, not an ADR-level architectural call. In the deprecation case, the old ADR's Decision section is not false — the team did pick Redis — but the context (there is a job queue layer) simply no longer exists.

The deprecation protocol — one file, not two

Unlike supersession, deprecation touches exactly one file. There is no second ADR to write and no bidirectional pointer to maintain. The three changes are:

  1. Status: Deprecated — this is the canonical value. Do not use Obsolete, Retired, Archived, or Inactive. These non-canonical variants cause the ADR GitHub Action auto-index job to treat the file as having an unrecognized status, which produces a broken row in the generated index table. The five canonical values the tooling knows are Proposed, Accepted, Superseded, Deprecated, and Rejected.
  2. A Notes entry in the format Deprecated YYYY-MM-DD: [one-sentence reason]. Written at the top of the Notes section in reverse-chronological order, consistent with how all Notes entries are written.
  3. Optionally: Deprecated-by: [pointer] — a PR URL, Jira ticket, migration guide URL, or commit SHA that explains why the decision became irrelevant. This field is a convention, not a standard, and is not verified by CI.

Here is what the change looks like for the two most common ADR formats.

Nygard format — before:

# ADR 0023: Use Redis for asynchronous job queue

Status: Accepted

## Context

The application needs a durable queue for background email delivery and PDF
generation jobs. We evaluated Redis (via Sidekiq) and RabbitMQ.

## Decision

We will use Redis via the Sidekiq library for background job processing.

## Consequences

Positive: Sidekiq's visibility dashboard is excellent. Redis reuse (already
used for session caching) keeps infrastructure simple.
Negative: Redis is not a message broker by design; if queue semantics grow
complex we may need to revisit.

Nygard format — after deprecation:

# ADR 0023: Use Redis for asynchronous job queue

Status: Deprecated
Deprecated-by: PR#847 — Redis queue removal (migrated to Temporal)

## Context

The application needs a durable queue for background email delivery and PDF
generation jobs. We evaluated Redis (via Sidekiq) and RabbitMQ.

## Decision

We will use Redis via the Sidekiq library for background job processing.

## Consequences

Positive: Sidekiq's visibility dashboard is excellent. Redis reuse (already
used for session caching) keeps infrastructure simple.
Negative: Redis is not a message broker by design; if queue semantics grow
complex we may need to revisit.

## Notes

Deprecated 2026-05-31: job queue layer removed entirely in PR #847; background
work migrated to Temporal Cloud. No replacement ADR — Temporal is a vendor
procurement decision managed at the infrastructure level.

MADR frontmatter format — before:

---
status: Accepted
date: 2024-03-10
deciders: alice, bob, carol
---

# Use Redis for asynchronous job queue

MADR frontmatter format — after deprecation:

---
status: Deprecated
deprecated-by: "PR#847 — Redis queue removal"
date: 2024-03-10
deciders: alice, bob, carol
---

# Use Redis for asynchronous job queue

Note that in both formats the original Context, Decision, and Consequences sections are left untouched. Those sections are permanent history. The deprecation is signaled entirely through the Status field, the optional Deprecated-by pointer, and the Notes entry — the three additions that sit outside the historical body of the decision.

The Deprecated-by field — optional and CI-silent

The Deprecated-by field is a convention, not a standard — it appears in neither the original Nygard template nor the MADR specification. It exists because practitioners found it useful to record a specific artifact that explains the deprecation, parallel to the way Superseded-by records the successor ADR for a superseded decision.

The key difference from Superseded-by: Deprecated-by is not verified by the CI supersession integrity check. The integrity check (job 3 in the ADR GitHub Action workflow) works by resolving every Superseded-by value as a filename in the decisions directory and failing if the file does not exist. It cannot apply the same logic to Deprecated-by because the pointer is not an ADR file — it is typically a PR URL, a Jira or Linear ticket, a migration guide URL, or a commit SHA. None of these are ADR filenames, so filename resolution doesn't apply.

Valid values for Deprecated-by include:

When to omit the field entirely: if the deprecation resulted from a diffuse context-collapse — a team reorganization, a general platform migration, a gradual sunset without a single identifiable artifact — write a plain Notes entry describing the situation and leave Deprecated-by out. A vague Deprecated-by value adds noise without adding traceability. The Notes entry is always sufficient on its own; Deprecated-by is only worth including when a specific artifact is the authoritative explanation and a future reader would clearly benefit from the direct link.

Supersession vs deprecation — the decision table

The distinction between supersede and deprecate collapses in practice to a single question: is there a named successor ADR? If yes, supersede. If no, deprecate. But the scenarios that arise in real ADR directories are messier than that binary. This table covers the cases teams most often ask about.

Scenario Right call Why
Switched from Redis to Valkey as the job queue backend Supersede A new ADR exists ("Switch to Valkey for job queue backend"). The Decision section of the old ADR named Redis; following it today means setting up Redis. The choice is factually reversed. Write the new ADR, set old ADR to Superseded, add bidirectional pointers.
Redis queue removed entirely in favor of Temporal (workflow engine) — no new "pick Temporal" ADR was written because Temporal is a vendor procurement decision Deprecate There is no "pick Redis or Valkey" successor decision. The entire job-queue architectural layer is gone. The old ADR's context is void. Deprecated-by: PR#847 is the right pointer; no new ADR is needed or appropriate.
The team that owned the ADR was merged into another team — no relevant architectural change occurred Keep (no change) Team org changes don't make an architectural decision irrelevant. The decision still governs the system it governs. If the new team disagrees with the decision, they should write a superseding ADR — not deprecate on organizational grounds.
Library used in the ADR went end-of-life (e.g., the Sidekiq version the ADR chose is now EOL) Deprecate only if the ADR is about the library itself; annotate if the ADR is about a higher-level choice the library implements An ADR titled "Use Redis for job queuing" is about the architectural call, not the specific Sidekiq version. Annotate it with a Notes entry explaining the EOL situation and the version upgrade decision. An ADR titled "Use Sidekiq 6 for background processing" is specifically about the library — deprecate it and write a new ADR for the replacement.
Decision was reversed without a successor ADR being written first Write the successor ADR first, then supersede Do not deprecate when the decision was actually reversed. Deprecation says "the context dissolved." If the team made a new choice, that new choice deserves its own ADR. The correct sequence is: write new ADR → supersede old ADR in the same PR. Using Deprecated as a workaround for "we changed our mind but didn't write it up" creates an audit trail that says "this area dissolved" when actually the team made a deliberate new decision.
A component referenced by the ADR is removed, and the ADR is about a cross-cutting concern that partially still applies Annotate, not deprecate If the ADR is about a pattern or principle that applies beyond the removed component, it should not be deprecated just because one of its referenced systems is gone. Add a Notes entry: "Update YYYY-MM-DD: the Redis component this ADR governed was removed in PR#847. The caching-strategy principles in this ADR continue to apply to the Memcached and in-process cache layers." Deprecation applies to the entire decision's context being void — not to a partial obsolescence.

Why deletion is almost never right

The instinct to delete an ADR that is "no longer relevant" is understandable — directories fill up, stale files feel like clutter, and a lean decision log seems more useful than a sprawling one. But deletion breaks the audit trail in three distinct ways that are hard to repair after the fact.

1. Deleted files still appear in git history — and create orphan CI failures. If any other ADR in the directory ever pointed at the deleted file with a Superseded-by or Supersedes line, the CI supersession integrity check will now fail on every PR that touches the decisions directory. The check resolves every pointer by filename; a pointer to a deleted file is an unresolvable reference. The reviewer sees a CI failure, traces it to a missing file, and has to reconstruct — from git history — why the file was deleted and what the relationship was. This is more maintenance burden than the original stale ADR created.

2. The absence of an ADR is indistinguishable from "no decision was made." A Deprecated ADR says: "this decision was made; we governed this system this way; the context has since dissolved." A missing ADR says nothing — a reader examining the directory cannot tell whether the team carefully considered and then deprecated the decision, or whether the decision simply never existed. The ADR practice's core value is making the history of architectural reasoning inspectable. Deletion makes the past look like a blank rather than a superseded or deprecated choice.

3. Adjacent ADRs that reference the deleted file by number become orphaned references. It is common for ADRs to cite related decisions: "This decision supersedes ADR-0023 (see 0023-redis-job-queue.md) and should be read alongside ADR-0031 (0031-background-processing-strategy.md)." If ADR-0023 is deleted, every ADR that cites it now contains a dead reference. Future engineers reading those ADRs encounter a gap in the chain they cannot follow without going into git history — which defeats the purpose of keeping the ADR directory as a navigable, self-contained record.

The one justified deletion is a Proposed ADR whose PR was closed without merging. A Proposed ADR that never reached the canonical branch never governed any implementation decision; it never appeared in another ADR's Supersedes or Superseded-by line; and its cleanup naturally happens at PR close rather than via a separate deletion commit. If such a file accidentally landed on the main branch before the PR was closed, a brief cleanup commit is acceptable — but add a commit message that explains the deletion was of an unmerged draft, so the git log entry is interpretable.

The archive question

Some teams propose moving stale ADRs to an archive/ subdirectory as an alternative to deletion — a way of cleaning up the "active" decisions directory without losing the files. This approach sounds reasonable but causes a specific class of breakage that is tedious to repair.

Every supersession pointer uses a filename relative to the decisions directory: Superseded-by: 0023-redis-job-queue.md. Moving the file to archive/0023-redis-job-queue.md silently breaks every pointer that names it. The CI supersession integrity check, which resolves pointers relative to the decisions directory, will fail for every ADR that references the archived file. Fixing those pointers requires editing every referencing ADR to update its Superseded-by value — which means those ADRs now have a misleading last-modified date and an irrelevant change in their git blame.

The correct mental model: ADR files stay in doc/decisions/ forever. The Status field is the archive signal. A directory that contains ADRs at Status: Deprecated and Status: Superseded alongside ADRs at Status: Accepted is not cluttered — it is correct. The accepted ADRs describe current practice; the superseded and deprecated ones describe history. Both are needed for the audit trail to be coherent.

If the concern is visual clutter when browsing the directory, the right solution is tooling: the ADR GitHub Action auto-index job generates a status table and can filter by status for display purposes. The Log4Brains static site generator renders a filterable browsable view of the same files. Neither requires moving or deleting files — they read Status from the frontmatter and present the directory accordingly.

"Archiving" is a classification you apply to a repository's ADR practice as a whole — for example, "this repository is read-only; no new decisions are being made" — not to individual ADR files. A repository-level archive annotation belongs in the decisions directory README, not in individual file relocations.

Mass deprecation when a component is removed

When a service is decommissioned or a significant architectural layer is removed, several ADRs may become obsolete simultaneously. A payment service removal might deprecate the ADR that chose Stripe, the ADR that chose the webhook retry strategy, the ADR that chose PCI-scoped network isolation, and the ADR that chose the reconciliation job schedule — four separate files that all governed the same removed component.

The protocol for mass deprecation:

  1. Open a single PR that touches only the ADRs covering the removed component. Do not intermix the deprecation with unrelated changes. The PR description is the audit artifact that explains why all these files changed together.
  2. Each ADR gets two changes only: Status changed to Deprecated, and a Notes entry in the format: Deprecated YYYY-MM-DD: [component name] removed in PR #NNN. No replacement ADR — [one-sentence reason, e.g. "migrated to managed service Stripe Treasury with no equivalent local decision"].
  3. Add a Deprecated-by field pointing to the removal PR: Deprecated-by: PR#847 — payment service decommission. When all the ADRs in a mass deprecation share the same removal PR, the same Deprecated-by value appears in every file — this is correct and intentional.
  4. The PR description lists every file changed and explains the component removal. Link the removal PR or ticket explicitly so the relationship is bidirectionally traceable: the removal PR links the ADR update PR; each ADR's Notes entry links the removal PR.

One common anti-pattern: suppressing or combining the ADR deprecation commits into the removal PR itself to "keep the diff clean." Resist this. The ADR updates belong in a separate, clearly-labeled PR because the ADR directory has its own reviewers (often the architecture board or lead engineers) who need to see and approve the deprecation decisions independently of the implementation work. Mixing ADR changes into a large infrastructure PR means the ADR changes receive less scrutiny and are harder to trace from the ADR directory later.

After the mass deprecation PR merges, run the CI supersession integrity check manually against the updated directory to confirm no existing ADRs reference the newly deprecated files in a Superseded-by pointer that now requires updating. A deprecated ADR can still be a valid Superseded-by target — the supersession chain remains intact — but the check will surface any inconsistencies introduced by the deprecation.

How WhyChose fits in

ADR retirement presupposes that the decisions reached the ADR directory in the first place. The harder upstream problem is the decisions that never made it — made in ChatGPT or Claude tabs during the original implementation sprint, never formalized into ADRs, and now impossible to supersede or deprecate because they were never recorded. When a component is eventually removed, the team has no documented rationale to point to: the deprecation Notes entry can say "no replacement ADR" but cannot explain what the original reasoning was.

The WhyChose extractor reads your AI chat exports and surfaces those informally-made decisions: the exchange where the team chose Redis over RabbitMQ, the rationale for PCI network isolation, the trade-off discussion about the webhook retry strategy. Those extracted records — even when they were never promoted to formal ADRs — give the retirement PR something to link to. The deprecation Notes entry can say "original rationale in WhyChose extraction ID wc-2024-03-0034" rather than "no documented reason." Future engineers doing archaeology after the retirement find the reasoning even when nobody wrote an ADR at the time.

Get early access

Related questions

When should I deprecate an ADR rather than superseding it?

Deprecate when the decision is no longer operative but there is no single named successor ADR to point to. The core test: supersession is for when the Decision section became factually false (a new ADR explicitly reversed the choice); deprecation is for when the Context section became void — the component was removed, the team dissolved, the architectural area migrated away without a direct replacement decision. If you can write a Supersedes: NNNN-old.md line in a new ADR and it makes sense, supersede. If there is no such new ADR and the decision's context has simply dissolved, deprecate.

Can you delete an ADR that was a mistake?

Almost never. The only justified deletion is a Proposed (never-Accepted) ADR whose PR was closed without merging. Once an ADR has been Accepted and used to guide any implementation decision, it is permanently part of the audit trail. Deleting it removes the record that the decision existed — exactly the loss the ADR practice is designed to prevent. An Accepted ADR that was later invalidated should be moved to Superseded or Deprecated, not deleted. Git history will show the deletion regardless, and a reviewer following the supersession chain will hit a dead end.

What can the Deprecated-by field point to?

Deprecated-by can point to any artifact that explains why the decision became irrelevant — a PR number, a commit SHA, a Jira or Linear ticket, a migration guide URL, or another ADR that covers the successor domain at a higher level of abstraction. Unlike Superseded-by, Deprecated-by is not verified by CI for file existence. If no specific artifact explains the deprecation, omit the field and write a plain-text reason in a Notes entry instead.

How do I handle mass deprecation when a component is removed?

Open a single PR touching only the ADRs covering the removed component — no interleaved unrelated changes. Each ADR gets Status: Deprecated and a Notes entry in the format Deprecated YYYY-MM-DD: [component] removed in PR #NNN. No replacement ADR — [brief reason]. The PR description lists all files changed, explains the removal, and links the removal PR. Mass deprecation in one atomic PR keeps the audit trail clean: a reviewer can see exactly which architectural decisions became irrelevant in the same action as the removal.

Further reading