Most work needs none of these. Write one only when it is useful.
Which one to write
| Situation | Write | Where |
|---|---|---|
| A routine change within established conventions, such as a bugfix, a refactor, or a feature that follows existing patterns. | A pull request only. Code review is the gate. | - |
| An architecturally significant decision, even if nobody disputes it. Also any decision that is hard or costly to reverse, including an agreed exception to these standards. | An ADR to record it. | The owning repository’s docs/adr/. With no owning repository, under RFCs and ADRs in Confluence. |
| A different, contested, or cross-cutting change that needs agreement before anyone builds it. | An RFC first to discuss it, then an ADR if it sets a pattern others must follow. | The owning repository’s docs/rfc/. With no owning repository, or when it reaches beyond one team, under RFCs and ADRs in Confluence. |
| Work that takes more than a sprint or one engineer, changes the data model or a contract, adds an integration, involves money movement or regulatory reporting, or needs a staged rollout. | A design document before implementation. | The owning team or squad’s section of the DSE Confluence space. |
A design document is an implementation plan. It does not replace an ADR, which records a decision.
The ADR bar is lower than the RFC bar. An ADR needs a significant decision. An RFC needs a contested one. Most ADRs record a clear choice that nobody disputes, so most ADRs have no RFC. Never write an RFC only to justify an ADR.
Where they live
Prefer the owning repository. A decision kept beside the code stays in Git history, gets reviewed in the same pull request, and is available to people and agents working in that repository.
- In the owning repository, keep RFCs under
docs/rfc/and ADRs underdocs/adr/. Each folder must have a template. This is the default for a decision that one repository enforces. - Under RFCs and ADRs in Confluence, keep a decision that has no owning repository, or a proposal that reaches beyond one team or would change these standards. Create the page as a child of RFCs and ADRs, using the templates below.
Keep design documents in the owning team or squad’s section of the DSE space. Each team page says where. Link every document from the ticket and the pull request.
What “architecturally significant” means
Write an ADR when a decision affects one or more of:
- Structure. How code, packages, or layers are organized.
- Cross-cutting non-functional requirements. Accessibility, performance, security, internationalization, theming, or operability.
- Dependencies. Adopting or dropping a library, or adding an integration boundary.
- Public interfaces. APIs, contracts, token names, or anything else consumers rely on.
- Construction techniques and conventions. A pattern that other code is expected to follow.
Also write one when the decision is hard to reverse. If a future contributor would ask “why is it done this way?”, the answer belongs in an ADR.
“Architecturally significant” is a judgement call, and people will disagree at the margin. Code review and the relevant Engineering Navigator settle it, not an exhaustive checklist.
Stack-specific triggers
Watch for these in our stack:
- A Scala effect-system or core library choice.
- A JDK version move (for example, 17 to 21).
- A GKE, Terraform, or Atlantis module pattern that other services will copy.
- A cross-service contract change, including any change to
tradovate/master-scheme. - An agreed exception to these standards.
Repositories add their own triggers in docs/adr/README.md.
What an ADR contains
An ADR records one decision. Keep it short. The ADR template follows Michael Nygard’s original format (Context, Decision, Status, Consequences) and adds Alternatives considered.
Every ADR must name its trade-offs. If you cannot name a single downside, you have not questioned the decision hard enough.
When an RFC produced the decision, link the RFC from the ADR and summarize it. Do not copy its alternatives analysis. The RFC is the record of the discussion, and the ADR is the record of the decision.
ADR status lifecycle
An accepted ADR is a permanent record. Never edit an accepted decision. To change it, write a new numbered ADR that supersedes it, and link the two ADRs both ways.
| Status | Meaning |
|---|---|
proposed |
Under discussion; not yet binding. |
accepted |
The current decision. Immutable. |
superseded |
Replaced by a later ADR. Set superseded-by to its number. |
deprecated |
No longer applies, with no direct replacement. |
stateDiagram-v2 direction LR [*] --> proposed proposed --> accepted accepted --> superseded: a new ADR replaces it accepted --> deprecated: no replacement superseded --> [*] deprecated --> [*]
RFC status lifecycle
| Status | Meaning |
|---|---|
draft |
The author is still writing it. |
in-review |
Open for comment until its decision deadline. |
accepted |
The decider approved the proposal. |
rejected |
The decider turned it down. The status quo stands. |
implemented |
The accepted proposal has shipped. |
superseded |
A later RFC replaced it. |
stateDiagram-v2 direction LR state "in-review" as in_review [*] --> draft draft --> in_review in_review --> accepted in_review --> rejected accepted --> implemented accepted --> superseded: a later RFC replaces it implemented --> superseded: a later RFC replaces it rejected --> [*] implemented --> [*] superseded --> [*]
Require a real alternative
Every RFC and design document must consider at least one real alternative. One alternative must be do nothing / status quo. Explain the cost of the status quo and why it is not enough. A decision without an alternative is not a decision. It is only a preference.
An RFC also needs a Risks, trade-offs, and what could break section. Send back an RFC that lacks either section.
Time-box with a named decider
Give every RFC a clear decision deadline and one named decider. An RFC left open becomes the default decision, so “a decision by default” must go to a real owner, not happen because time ran out. If the deadline passes without a decision, keep the status quo.
Numbering and index
Number decisions in order and use four digits: ADR-0001, RFC-0001. Keep an index at docs/adr/README.md so people can find decisions and cite them consistently. See adr.github.io for numbering rules and tools.
Templates
Copy a template, then fill it in. Its headings are a checklist.
The ADR and RFC templates below are the only templates. Copy them into the owning repository as docs/adr/template.md and docs/rfc/template.md. For an RFC or ADR that lives in Confluence, paste the same Markdown into a new page under RFCs and ADRs. For design and status documents kept beside code, NT-NinjaTrader/ntc-core uses a per-project _TEMPLATE.md with a status field.
- Design document. Duplicate the [TEMPLATE] Technical Design Document - TDD. Do not skip Monitoring/Alerting or Testing.
- RFC. Copy the RFC template.
- ADR. Copy the ADR template.
ADR template
Name the file NNNN-short-title.md, using the next four-digit number.
---
status: proposed # proposed | accepted | superseded | deprecated
date: YYYY-MM-DD # the date of the decision, or of the last status change
supersedes: # OPTIONAL: the ADR number this one replaces, e.g. 0003
superseded-by: # OPTIONAL: the ADR number that replaced this one
rfc: # OPTIONAL: a link to the RFC that produced this decision
decider: # the one person who owns the call
---
# ADR-NNNN: The decision, stated as a short outcome
## Context
Why this decision is needed now, and the forces at play. Two to four sentences. Describe the problem neutrally.
## Decision
What we will do, in one or two sentences.
## Alternatives considered
1. Do nothing or keep the status quo. The cost, and why it is not enough.
2. Option B. Its trade-offs.
If an RFC produced this decision, summarize it and link the RFC instead.
## Consequences
What becomes easier, what becomes harder, and what we accept. Name at least one downside.RFC template
Name the file NNNN-short-title.md, using the next four-digit number.
---
status: draft # draft | in-review | accepted | rejected | implemented | superseded
date: YYYY-MM-DD # the date of the last status change
author: # your GitHub handle
decider: # the one person who makes the call
deadline: YYYY-MM-DD # if undecided by then, the status quo stands
---
# RFC-NNNN: Short title
## Problem / Motivation
What problem this solves, why now, and who feels it. Leave the solution out of this section.
## Proposal
The approach, in enough detail to evaluate.
## Scope and boundaries
What is in scope, and what is not.
## Alternatives considered
1. Do nothing or keep the status quo. The cost, and why it is not enough.
2. Option B. Its trade-offs, and why it was not chosen.
## Risks, trade-offs, and what could break
Failure modes, migration hazards, and effects on existing consumers.
## Rollout / migration
How this ships, and how existing code moves to it.
## Open questions
What the decider still needs to settle.Superseded templates
These older Confluence copies are superseded by the templates above. Do not start new documents from them:
- RFC Template, under Engineering Operating System. It lacks the required alternatives and risks sections.
- ADR - Architecture Decision Records and ADR-0 Template, under Squad: B2B → Research.
- [TEMPLATE] Design Document and the older Software Design Document Template. Use the [TEMPLATE] Technical Design Document - TDD instead.
Exceptions record an ADR
An agreed exception to these standards is hard or costly to reverse, so it needs an ADR. Add the ADR link to the exception itself. See exceptions for the process, and architecture for the standards these decisions implement.
Keeping documents current
Mark a design document or ADR as superseded instead of deleting it when the design changes in a major way. The record of why a past decision was made remains useful after the decision changes.