RFC vs ADR: One Is a Conversation, the Other Is a Receipt

RFC vs ADR: One Is a Conversation, the Other Is a Receipt

Published: October 31, 2026

Picture a repository with a folder called adr/ and 14 files in it. Eleven of them are six to twelve pages long, full of open questions, pasted-in comment threads and sections titled "Discussion". Ask what was actually decided in any of them, and nobody can say.

The folder was named after one document type and filled with another. It is a very common setup, and not a naming nitpick: the two documents answer different questions, live different lives, and fail in different ways.

I have already written about why ADRs only matter if they shape the decision and why AI-generated ADRs rationalize instead of decide. This post is about the boundary: where an RFC ends, where an ADR begins, and what to do when you only have the energy for one of them.

The short version

An RFC (Request for Comments) is a proposal that is still open. You write it before the decision, to collect objections, surface alternatives and get the affected people into the same conversation. The name comes from the internet standards process, and companies later borrowed it for internal proposals; the Rust project is a well-known public example. Its life cycle is roughly draft, review, accepted or rejected.

An ADR (Architecture Decision Record, popularized by Michael Nygard) is the record of a decision that has been made. You write it so that someone who joins in two years can read half a page and understand why the system looks the way it does. It has a context, a decision and consequences, and once accepted it is not edited. If the decision changes, you write a new ADR that supersedes the old one, and the chain stays readable.

RFC ADR
Question What should we do? What did we decide, and why?
Time Before the decision At the decision, kept afterwards
Length Often several pages, open questions allowed One page or less
Audience People who can influence the outcome People who live with the outcome
Life cycle Draft, review, accepted or rejected Proposed, accepted, superseded
Mutability Changes during review Immutable after acceptance

If you remember one thing: an RFC is a conversation, an ADR is a receipt.

One decision, both documents

Abstract definitions are easy to nod along to, so here is a concrete case.

A product has an orders database running on MySQL. Three teams touch it: the orders team owns the schema, billing reads and writes invoices against it, and the reporting team runs heavy analytical queries on a replica. The orders team wants to move to PostgreSQL, mainly for better JSON handling and partial indexes they would use right away.

The RFC

Moving a shared database is expensive and hard to undo, and three teams are affected. This is RFC territory. The document the orders team circulates might look like this:

# RFC: Move the orders database from MySQL to PostgreSQL

Status: Draft · Author: orders team · Review until: 2026-11-14

## Problem
Order metadata is stored as JSON text in a TEXT column; every filter on it
is a full scan. Three product features planned for Q1 need that filtering.

## Options
A. Stay on MySQL, migrate the column to the native JSON type
B. Move to PostgreSQL with a dual-write period
C. Move to PostgreSQL with a change-data-capture cutover

## Open questions
- Does reporting rely on MySQL-specific SQL? (reporting team to answer)
- Can billing tolerate 10 minutes of read-only during cutover? (billing to answer)
- Who owns the operational runbook for the first three months?

## Costs we know about / costs we don't
...

Notice what it contains: unresolved questions with names next to them, options that are genuinely still open, and a review deadline. It is allowed to be uncertain.

During review, things come out that the orders team could not have known. Reporting uses a MySQL-specific function in about forty queries, so option B's dual-write window would double their query-rewriting effort. Billing says a ten-minute read-only window is fine, but only outside the month-end close. Someone points out that option A solves the immediate JSON problem for a fraction of the effort, but does not give the partial indexes.

That feedback is the entire reason the RFC exists. If the orders team had just decided and announced, reporting would have found the forty queries in production.

The ADR

Two weeks later the review ends. The team picks option C, with the cutover scheduled outside month-end. Now the RFC has done its job, and what the organization needs to keep is much smaller:

# ADR-014: Orders database moves to PostgreSQL via CDC cutover

Status: Accepted · 2026-11-18 · Supersedes: ADR-003 (MySQL as primary store)

## Context
Order metadata filtering requires JSON querying and partial indexes.
Three consuming teams (orders, billing, reporting) share the database.
Billing tolerates a 10-minute read-only window outside month-end.

## Decision
Migrate to PostgreSQL using change-data-capture, with cutover in the first
week after a month-end close. Reporting rewrites its MySQL-specific queries
before cutover, not after.

## Consequences
- We operate one more database engine for the migration period.
- Reporting carries ~40 query rewrites; planned in their Q1.
- Rollback is possible until the CDC stream is switched off (see RFC-021).

It is short, it states the decision rather than the debate, and it links back to the RFC for anyone who wants the full story. Two years later, when a new engineer asks why the team runs PostgreSQL when the older services are on MySQL, this page answers it in a minute. The RFC, with its forty comments, would take an afternoon and still not tell them what the outcome was.

Notice also the line Supersedes: ADR-003. The old ADR is not edited or deleted. It still says "MySQL as primary store", and that was true when it was written. The chain tells the history.

When one document is enough

Not every decision needs both. A rough rule I use:

  • Small, local, reversible: an ADR is enough, or even just a commit message with a good explanation.
  • Crosses team boundaries, expensive or hard to reverse, many stakeholders: write an RFC first. Its outcome is one ADR, sometimes several if the RFC covered a bundle of decisions.
  • Cheap to undo, obvious, or already covered by a convention: neither.

To see the lower end of this, take API versioning. A single team owns an internal API consumed only by its own frontend. They need to decide how to version breaking changes: a /v2/ URL prefix or a header. Nobody outside the team cares, and if they choose wrong they can change it in a sprint because they control both sides. An ADR of ten lines, written in the pull request that introduces the first /v2/ endpoint, is the right size.

Now change one fact: the same API becomes public, with external customers who integrate once and rarely update. The versioning scheme is now a promise you will keep for years, support teams need to explain it, and the gateway team has opinions on routing. Same question, different cost of being wrong. This one deserves an RFC, and the ADR comes afterwards.

The size of the document should follow the cost of being wrong, not the importance of the topic to the author.

And the third category matters too. Choosing a date library, renaming a package or picking a linter is not worth either document. If the decision can be reverted in an afternoon, writing about it is the more expensive option.

Why the two keep blurring

If the distinction is this clear, why do the boundaries disappear in so many teams? In my experience, five reasons come up again and again.

The templates look the same. Context, options, decision. An ADR template and an RFC template share most of their headings, so it is easy to grab one and use it for the other. Add that some ADR templates (MADR, for example) contain "considered options" and "pros and cons" sections, and the ADR starts to invite debate.

The ADR becomes the discussion forum. The pull request that adds the ADR is where people finally read the proposal, so the argument happens in the review comments. The merge then records a decision, while the real reasoning is buried in a PR thread that nobody will find. The ADR itself reads like a one-sided pitch, because the objections were resolved somewhere else.

The RFC never gets closed. The review period ends and the document just stays in "Draft" forever. People implement whatever the loudest comment suggested. There is no accepted status, no record of the outcome, and six months later the RFC is cited by both sides of a new argument. This is the failure that produces the adr/ folder from the beginning of this post: nobody closes the loop, so open documents pile up in the place where decisions should be.

Different names for the same thing. Google-style teams write "design docs", others write "proposals" or "tech specs", some write RFCs that are really specs. When every company uses its own vocabulary, people carry the habits of their previous employer, and the labels stop meaning anything in the new one.

AI-generated documents try to be both. Ask a model for an ADR and you often get a hybrid: a long options analysis, a decision, a "status: accepted" line, all produced in one pass. It reads like an RFC that skipped the review and an ADR that skipped the decision. As I argued in the post on AI-generated ADRs, the missing part is the conversation among the people who would have disagreed.

A process that keeps them apart

You do not need heavy governance. This is enough for most teams:

  1. Decide whether the decision needs an RFC. Use the three-way rule above. Most do not.
  2. If it does, open the RFC with a review deadline and named reviewers. Questions get an owner. An RFC without a deadline is a wish.
  3. Close it explicitly. The author sets the status to accepted, rejected or withdrawn, and writes one sentence on why. This is the step teams skip.
  4. Write the ADR from the outcome. Keep it to a page. Link to the RFC from the ADR, and put the ADR's number into the RFC's header. Now a reader can go in either direction.
  5. When the decision changes, write a new ADR that supersedes the old one. Do not edit history.

Keep the two in separate places if you can: rfcs/ and adr/ in the repository, or two sections in your wiki. The folder structure alone prevents a surprising amount of confusion.

Signs that you are using the wrong form

A few symptoms I would look for:

  • Your ADRs are longer than two pages or have a "Discussion" section.
  • You find open questions in an ADR with status "Accepted".
  • Nobody can point at the outcome of an RFC without reading the comments.
  • Decisions get made in the RFC's comment thread, and the document is never updated.
  • Your RFCs have no deadline, no named reviewers, and have been in draft for more than a month.
  • The ADR was written after the code shipped, with the reasoning reconstructed from memory.
  • An engineer asks "why is it like this?" and the answer is a link to a 40-comment pull request.

If three or more of these sound familiar, the issue is probably not the template. The team is using one document to do two jobs, and neither gets done well.

Final thought

Use the RFC to find out what the decision should be, and the ADR to remember what it was. If you are unsure which one to write, ask whether there is still something you do not know. If yes, it is a proposal, and you need the comments. If no, it is a record, and you need one page.