---
title: "How to Write RFCs and ADRs"
description: "This guide covers what a good RFC and ADR answer, gives you a template to copy, and builds one in Oxynote, where the proposal becomes the record when its draft is merged."
canonical_url: "https://oxynote.io/blog/write-an-rfc-and-adr"
---

> Index of every page on this site: [llms.txt](https://oxynote.io/llms.txt)

Joe Beda, who co-created Kubernetes, once [described](https://news.ycombinator.com/item?id=23920963) what happened to its first design doc:

<blog-quote author="Joe Beda" href="https://news.ycombinator.com/item?id=23920963" source="Hacker News">

I wrote a design doc/PRD for k8s that outlined the basic API, distributed structure and why/how it related to open source and the marketplace. I lost it when I left google. It was a google doc IIRC and wasn't checked into source control.

</blog-quote>

Most teams lose decisions in smaller ways. The proposal is argued in one tool, the decision is recorded in another or not at all, and a year later nobody can say why the system works the way it does.

This guide covers what a good request for comments (RFC) and architecture decision record (ADR) answer, a template you can copy, and a decision built in Oxynote, from the first draft to the accepted record.

## Why Proposals and Decisions Get Lost

Most teams write proposals in Google Docs or Notion, because commenting there is easy. A reviewer selects a sentence, asks a question, and the author answers in the same thread. The trouble starts after a few rounds of comments, when it's hard to see what changed in the doc since you last read it. Once the decision is made, nothing marks which version was agreed. And the decision rarely gets copied anywhere more permanent.

Other teams keep their records as Markdown in git, next to the code. That gives them a review, a diff, and a history. But a pull request is a poor place to discuss writing, and people outside engineering rarely open the repository. Oxide, a company that builds server racks, keeps its design documents in a GitHub repository and [wrote about the trade-off](https://oxide.computer/blog/a-tool-for-discussion):

<blog-quote author="Ben Leonard, Oxide" href="https://oxide.computer/blog/a-tool-for-discussion" source="A Tool for Discussion">

Whilst a repo is a useful storage and collaboration tool, there are a number of drawbacks: it doesn't provide the best reading experience, is limited in terms of AsciiDoc support, and is challenging to share externally.

</blog-quote>

So teams end up choosing between a good discussion and a good record.

## An RFC and an ADR Are One Decision at Two Stages

An RFC, also called a design doc, is a proposal that asks for comments. An ADR records the decision once it's made, in the format Michael Nygard [described in 2011](https://cognitect.com/blog/2011/11/15/documenting-architecture-decisions): the context, the decision, and its consequences.

Most guides treat them as two documents. They work better as one page at two stages: a proposal while people discuss it, then a record once it's decided. The record keeps the reasoning that led to it, so someone who joins the team later can see why the decision was made.

## What a Good One Answers

A proposal is ready for review when it answers these questions:

- **Who decides, and by when**: one named decider and a deadline. Without them, a proposal turns into what one engineer calls ["just a long email"](https://buttondown.com/critical-path/archive/an-rfc-without-a-deadline-and-a-decider-is-just-a/).
- **What problem it solves**: the context, with the numbers as they were when you wrote it, such as "p99 was 340 ms in October".
- **What else was considered**: each option with what it costs and what it gives up.
- **What exactly is proposed**: a specific choice. "Improve the data architecture" is too broad for anyone to approve.
- **What changes as a result**: the consequences, the bad ones included.
- **What makes it done**: the confirmation, what has to be true for the decision to count as finished, such as a metric reaching a target.

Two rules keep the records useful. Write one only for a decision that is costly, risky, or confusing to reverse. And never edit an accepted decision. When it changes, write a new one that supersedes it, and link the two.

## A Template to Copy

The template below works in any tool that stores text, such as Confluence, Notion, or a Markdown file in your repository. Write the proposal with it first. Once the decision is made, the same page becomes the record: rename the "Proposal" heading to "Decision", answer or remove the open questions, change the status to Accepted, and replace the decider line with who accepted it and when.

```md [adr-template.md]
# ADR-<number>: <The choice, as a short sentence>

Status: Proposed | Accepted | Superseded by ADR-<number>
Proposed by <who> on <date>. Decider: <who>, by <date>.

## Context

<The problem, and what it costs today, with numbers and dates.>

## Options Considered

1. <Option>: <what it costs, and what it gives up>.
2. <Option>: <what it costs, and what it gives up>.

## Proposal

<The option you propose, specific enough to approve or reject.>

## Consequences

- <What changes, good and bad.>

## Confirmation

<What has to be true for this to count as done, such as a number to reach.>

## Open Questions

- <What you still don't know.>
```

Confirmation is often left as a sentence nobody checks. It names the metric the decision should improve, but the metric itself lives in a dashboard in another tool. Once the work ships, nobody goes back to check the metric, so nobody knows whether the decision did what it promised. Later in this guide, you'll see how to put a live chart in the record itself.

## Build It in Oxynote

Oxynote is a wiki whose pages are reviewed like pull requests and hold live charts from your own data. So in Oxynote, the proposal and the record are the same page. People discuss it in a draft, the decider approves it, and merging the draft makes it the record.

The following screenshots come from a demo workspace for Lastport, a made-up shipping company. Its ships report their position over satellite, and on 14 September 2026 that feed stopped for 47 minutes. ADR-0007 proposes a fallback for when the satellite feed goes silent: AIS, the position broadcasts every ship sends anyway.

### Write the Proposal in a Draft

Create a page for the decision, then open **Page Options**, the **⋯** menu at the top right of the page, and click **Make Reviewable**. The page now has a main version, which everyone reads, and a draft, where the proposal is written and discussed. Until the draft is merged, the main version can hold a single line saying the proposal is in the draft.

To mark the status, click the plus next to **Tags** in the page header, and create a tag such as `Proposed`. The other statuses get tags of their own, `Accepted` and `Superseded`.

### Discuss It in Comments

Reviewers comment on the draft the way they would in a doc. Select a few words and click **Comment** to ask about them, or click the drag handle next to a block and choose **Add Comment** to comment on the whole block. A new comment notifies the page's maintainers, the people who have edited it, and a reply notifies everyone in the thread, in their **Inbox**.

![A comment thread on the words "stop for 2 minutes" in a decision record's draft, with a question and the author's reply](https://oxynote.io/images/blog/adr-thread.webp)

Comments stay with the draft. When the draft is merged, they don't carry over to the main version. So write the outcome of a thread into the page itself. Lastport's record explains its 2 minutes in the Decision section, because the question about it will come up again.

### Approve It

To ask the decider for a review, click **Reviewers** in the page header and **Invite to review**. They get a notification in their **Inbox**, read the draft, and click **Approve Draft** at the top right of the page. The page header then lists them under **Approved by**.

![The reviewers list of a decision record's draft, with Simon under Approved by](https://oxynote.io/images/blog/adr-reviewers.webp)

An approval stays in place when the draft changes. So if you change the proposal after an approval, open **Reviewers** and click the refresh icon next to the reviewer's name to ask for another review.

### Merge It as the Decision

Before merging, turn the proposal into the record in the draft, as the template section describes. Write who accepted it and when, and swap the `Proposed` tag for `Accepted`. Then click the arrow next to **Approve Draft** and choose **Merge Draft into Main**.

The main version is now the record, and it only changes through another draft.

![An accepted decision record with its context, the three options considered, and the decision](https://oxynote.io/images/blog/adr-full.webp)

### Show Whether It Worked

To show whether the decision worked, put a **Live Metrics** chart under Confirmation. Type `%%` to add one. The chart runs its query each time someone opens the page, so the record shows today's numbers.

Lastport's record has two charts. The first counts the vessels with stale positions each hour, from Lastport's PostgreSQL:

```sql
SELECT $__timeGroupAlias(ts, '1h'), max(vessels) AS vessels
FROM stale_vessels
WHERE $__timeFilter(ts)
GROUP BY 1
ORDER BY 1
```

`$__timeFilter` keeps the rows inside the chart's time range, and `$__timeGroupAlias` groups them by hour.

The second shows the share of positions that came from AIS. In the satellite outage on 20 October, before the fallback shipped, 9 vessels went stale. In the next one, on 5 November, AIS filled in almost 40 percent of positions, and no vessel went stale.

![Two charts under Confirmation: vessels with stale positions, with a spike on 20 October, and positions from AIS, with a spike on 5 November](https://oxynote.io/images/blog/adr-confirmation.webp)

### Revisit It

A decision that made sense when it was accepted can stop making sense months later. To be reminded, add a reminder in the draft before you merge it, since the main version is read-only. Hover the page title, click the leaf icon next to it, click **Add Hook**, and choose **Scheduled Reminder**. Merging copies it to the main version. Lastport's record asks for a read-through on 9 April 2027, six months after it was accepted. For your own record, choose **In 6 months**. When the date comes, the page's maintainers get a notification in their **Inbox**.

![The Freshness Hooks menu of a decision record, with a scheduled reminder on 9 April 2027](https://oxynote.io/images/blog/adr-hooks.webp)

### Supersede, Don't Edit

When a decision changes, write a new record instead of editing the old one. The new one says which decision it replaces. Tag the old record `Superseded` and add a link to the new one. That's the only change the old record gets. To get a page's link, copy its address from the browser, or click a block's drag handle and choose **Copy Link** to link to one section.

### Find Decisions Later

Every record sits in one page tree, such as under a **Decisions** page. The sidebar's **Tags** section lists the pages under each tag, so the accepted decisions are one click away. To find a decision by what it says, press **⌘K** (**Ctrl+K** on Windows and Linux) and search across every page.

## Wrapping Up

A good proposal names its decider and deadline, compares real options, and says what makes it done. In Oxynote, the proposal is discussed in a draft, approved by the decider, and merged as the record. Its Confirmation section shows live whether the decision did what it promised.

A good place to start is the next decision your team argues about. Copy the template into a reviewable page, and invite the decider to review it. To put live charts under Confirmation, see how to connect [Prometheus](https://oxynote.io/blog/connect-prometheus), [PostgreSQL](https://oxynote.io/blog/connect-postgresql), or [Loki](https://oxynote.io/blog/connect-loki).

Oxynote is open source and runs as one Docker container: [github.com/oxynote/oxynote](https://github.com/oxynote/oxynote). If you need help or have a suggestion, come talk to us on [Discord](https://discord.gg/mNJd5zJkvC).

## Sitemap

See the full [sitemap](https://oxynote.io/sitemap.md) for all pages.
