Definition
- ADR (Architecture Decision Record) -- a short document capturing one significant decision: the context, the decision made, alternatives considered, and consequences.
- RFC (Request for Comments) -- a broader proposal describing a significant proposed change, circulated for stakeholder feedback before commitment.
- Append-only -- ADRs are never rewritten; a new ADR that supersedes the old one is added, preserving the history of how thinking evolved.
- Status -- an ADR can be proposed, accepted, deprecated, or superseded.
- Version-controlled -- stored in the same Git repository as the code, going through pull-request review.
Imagine National Bank of India decides to switch settlement from overnight batch to real-time. An RFC is the detailed proposal circulated to all departments -- what we want to change, why, the options, the risks -- inviting everyone to comment before commitment. An ADR is the official minute recorded once a specific decision is made -- we chose real-time on this date, for these reasons, with these trade-offs. Keeping both in the same filing system as the operational manuals means a new manager years later can understand exactly why the bank works the way it does.
Understanding the Concepts
What is an Architecture Decision Record?
An ADR documents a single architecture decision in a consistent, lightweight format. It is deliberately short -- often one page -- because its value is in being written at all and being easy to read later.
# ADR-003: Use Kafka for Inter-Service Events
## Status
Accepted (2024-01-15)
## Context
The account-ledger and fraud-detection services at National Bank of India
need to communicate asynchronously. The ledger publishes account events
(deposits, withdrawals, transfers) and the fraud service consumes them.
We need reliable, ordered, high-throughput event delivery.
## Decision
We will use Apache Kafka as the event backbone.
## Alternatives Considered
- **RabbitMQ** -- simpler setup but lacks log-based replay and
partition-level ordering at high throughput.
- **AWS SQS + SNS** -- managed but no ordering guarantees within
a partition and no replay from offset.
- **Direct REST calls** -- synchronous coupling, no buffering,
a fraud-service outage would block ledger writes.
## Consequences
- **Easier:** Replay from any offset for debugging and reprocessing.
Partition-key ordering by account_id. High throughput.
- **Harder:** Operational overhead of managing a Kafka cluster
(or cost of a managed service). Team must learn consumer
group semantics and offset management.
What is a technical RFC?
An RFC is broader and comes earlier. It proposes a significant change and seeks feedback before the team commits. After discussion, the team adopts it (often recording the outcome as an ADR) or rejects it.
# RFC: Migrate Settlement from Overnight Batch to Near-Real-Time
## Author
Pankaj (Architect)
## Motivation
The current overnight batch settlement means customers do not see
transfer results until the next business day. Competitors offer
near-real-time settlement. Customer complaints have increased 40%.
## Proposed Design
Replace the nightly batch job with a Kafka-driven event pipeline.
Each transfer event triggers immediate settlement processing.
Use Kafka transactions to ensure exactly-once semantics.
## Alternatives
1. Optimize the batch to run every hour (lower risk, still not real-time)
2. Use AWS Step Functions for orchestrated settlement (vendor lock-in)
## Risks
- Higher operational complexity with streaming infrastructure.
- Requires idempotent settlement logic to handle replays.
## Migration Path
Phase 1: Dual-write to batch and stream. Phase 2: Switch reads.
Phase 3: Decommission batch.
## Open Questions
- What is the acceptable latency SLA for near-real-time?
- Do we need to support replay of settlement events for auditing?
Why version-control them alongside code?
Three reasons. Traceability: every decision has a date, author, and reviewers through the pull-request process, which auditors in a bank require. Onboarding: new engineers read ADRs to understand why the system is shaped the way it is. Preventing re-debate: when someone asks why not X, the answer is a link to the ADR.
# ADRs live in the repo, versioned like code
ls docs/adr/
001-use-postgresql-for-ledger.md
002-use-bigdecimal-for-money.md
003-use-kafka-for-events.md
004-settlement-near-real-time.md
# Who decided and when?
git log --oneline docs/adr/003-use-kafka-for-events.md
abc1234 Pankaj 2024-01-15 Accept ADR-003: Use Kafka for events
def5678 Rajesh 2024-01-12 RFC: propose Kafka for inter-service events
What makes a good ADR?
Concise context, a clear unambiguous decision, and honest trade-offs. A reader should know exactly what was decided without interpretation. The trade-offs should state plainly what you give up.
package com.bank.ledger.event;
import java.math.BigDecimal;
/**
* This event class exists because of ADR-003.
* We chose Kafka over SQS for ordered, replayable events.
* See docs/adr/003-use-kafka-for-events.md for the full reasoning.
*/
public record AccountEvent(
String accountId,
String eventType,
BigDecimal amount,
String correlationId
) {}
How are ADRs numbered and managed?
ADRs are numbered sequentially and append-only. You never rewrite an old ADR. If a decision is superseded, you add a new ADR that references the old one and mark the old one as superseded.
# ADR-005: Switch from Kafka to AWS MSK Serverless
## Status
Accepted (2024-06-01)
Supersedes: ADR-003
## Context
Managing a self-hosted Kafka cluster proved operationally expensive.
AWS MSK Serverless removes cluster management while preserving
Kafka's API and ordering guarantees.
## Decision
Migrate to AWS MSK Serverless.
## Consequences
- **Easier:** No cluster management, automatic scaling.
- **Harder:** Vendor lock-in to AWS, slightly higher per-message cost.
How do ADRs help with compliance?
In a regulated bank, auditors ask why specific technology decisions were made. ADRs provide a dated, authored, reviewed record that satisfies compliance requirements.
# Auditor asks: "Why is customer data encrypted at rest?"
git log docs/adr/002-encrypt-customer-data.md
abc1234 2023-09-10 Pankaj Accept ADR-002: Encrypt all customer data at rest
Reviewed-by: Rajesh, Priya (Security)
Approved in PR #128
What are common mistakes?
The most common mistakes are not writing ADRs at all (relying on tribal knowledge), writing ADRs that are too long to read, editing old ADRs instead of adding new ones, and storing them in a wiki that nobody updates instead of in Git.
# WRONG -- no ADR written
"We use Kafka because... I think Pankaj said so in a meeting?"
# CORRECT -- ADR in Git
"We use Kafka because of ADR-003: ordered, replayable events.
See docs/adr/003-use-kafka-for-events.md"
What should a senior engineer know?
The discipline is not bureaucracy -- it is cheap insurance. A one-page ADR takes twenty minutes to write and saves days of future confusion and repeated arguments. In a regulated industry it demonstrates sound governance. Senior engineers champion ADR culture and make writing them part of the definition of done for significant decisions.
Visual Overview
RFC and ADR Lifecycle
─────────────────────
┌──────────────┐ ┌──────────────┐ ┌──────────────┐
│ RFC Draft │────▶│ Discussion │────▶│ Decision │
│ (proposal) │ │ (comments, │ │ (accept or │
│ │ │ questions) │ │ reject) │
└──────────────┘ └──────────────┘ └──────┬───────┘
│
▼
┌──────────────┐
│ ADR Written │
│ (numbered, │
│ append-only) │
└──────────────┘
ADR Statuses:
┌──────────┐ ┌──────────┐ ┌─────────────┐
│ Proposed │────▶│ Accepted │────▶│ Superseded │
└──────────┘ └──────────┘ │ by ADR-005 │
└─────────────┘
In Git:
docs/adr/
001-use-postgresql.md (accepted)
002-encrypt-data.md (accepted)
003-use-kafka.md (superseded by 005)
004-settlement-realtime.md (accepted)
005-switch-to-msk.md (accepted, supersedes 003)
Key Takeaway
An ADR captures one architecture decision in a consistent format: context, decision, alternatives, and consequences. It is short by design -- often one page -- because its value is in being written and easy to read later. ADRs are numbered and append-only, so you never rewrite history; you add a new ADR that supersedes the old one.
An RFC is broader and earlier. It proposes a significant change and circulates for feedback before the team commits. After discussion, the outcome is often recorded as an ADR. Both documents live in the Git repository alongside the code, going through the same pull-request review.
Version-controlling them gives traceability (date, author, reviewers for auditors), onboarding (new engineers understand why things are the way they are), and prevents re-debate (the answer to why not X is a link to the ADR that already weighed it).
Remember one sentence: an ADR takes twenty minutes to write and saves days of future confusion, re-debate, and audit scrambling by documenting the decision, alternatives, and honest trade-offs.
---