← All posts

Making Decisions Legible

How to record and communicate technical decisions so they survive the future: Architecture Decision Records, RFCs, the C4 model, and sequence diagrams.

architecture
tech-lead
engineering

Making Decisions Legible

A good decision that no one understands six months later is, in practice, a liability. The team will either cargo-cult it (preserving it without knowing why, even after the reason has expired) or rip it out (destroying a constraint they didn't know existed). Both happen constantly, and both are failures of legibility, not of the original decision.

The distinctive technical work of a lead is not just making good calls — it's making them communicable: recording the why so the decision survives contact with people who weren't in the room, including your own future self. This chapter covers the four tools that do most of that work.

Architecture Decision Records (ADRs)

An ADR is a short document — usually under a page — that captures one significant decision and the reasoning behind it, stored in version control alongside the code. The point is not bureaucracy; it's that the reasoning is the valuable part, and reasoning evaporates from memory and chat logs within weeks.

A battle-tested ADR structure:

A worked example, compressed:

# ADR-014: Use a modular monolith for the v1 platform

Status: Accepted (2025-03-12)

## Context
Team of 6 engineers, pre-product-market-fit, requirements changing weekly.
We need fast iteration and simple operations. Some engineers have lobbied
for microservices "to be ready to scale."

## Decision
Build a single deployable modular monolith with enforced module boundaries
(Orders, Catalog, Billing), each owning its own schema. No service split
until a concrete forcing function appears (team growth or divergent scaling).

## Consequences
+ Simple local dev, atomic refactors, one deploy pipeline.
+ Module boundaries give us clean seams to extract services later if needed.
- We scale the whole app together for now (acceptable at current load).
- Requires discipline to keep module boundaries from eroding; we'll enforce
  with import-linting in CI.

Why this is powerful: two years later, when someone asks "why aren't we on microservices like everyone else?", the answer is right there with its context — and they can see whether the forcing function it named has actually arrived. The ADR makes the decision revisable on its own terms instead of mysterious. The status field also lets decisions evolve honestly: you don't delete a superseded ADR, you mark it superseded and link forward, preserving the history of how thinking changed.

A lightweight norm that works well: write an ADR for any decision that is hard to reverse or surprising to a newcomer. Don't write one for routine choices — that just creates noise.

RFCs (request for comments)

Where an ADR records a decision, an RFC is the document used to propose and discuss a significant change before it's decided. Someone writes up the problem, the proposed approach, the alternatives considered, and the tradeoffs, then circulates it for written feedback from the team.

The value isn't the document; it's what writing forces. Writing a proposal down exposes the holes in it — the hand-waving that survives a hallway conversation rarely survives having to be written in full sentences. RFCs also let people who weren't in the room contribute, create a durable record of why alternatives were rejected (which prevents re-litigating them endlessly), and give quieter team members a channel that doesn't require winning a live debate.

An RFC and an ADR often pair up: the RFC is the discussion, and the resulting decision is captured as an ADR once consensus forms. For small or reversible decisions, skip the ceremony — RFCs are for changes big enough that getting them wrong is costly.

The C4 model

Diagrams are how you communicate structure, but most architecture diagrams fail the same way: they try to show everything at once and become an unreadable tangle of boxes. The C4 model fixes this with a simple idea borrowed from maps — different zoom levels for different audiences. You don't put every street on a map of the country.

C4: zoom in one level at a time1 · ContextYour system as one box + the users and external systems it talks to. For everyone, including non-technical.2 · ContainersThe deployable/runnable pieces: web app, API, database, queue. The high-level tech shape. For technical staff.3 · ComponentsInside one container: the major modules and their responsibilities. For developers on that system.4 · CodeClasses/functions — usually generated, rarely hand-drawn. Most teams stop at level 3.

The discipline the C4 model enforces is one level of abstraction per diagram. The reason most architecture diagrams are useless is that they mix levels — a box labeled "AWS" next to a box labeled "the validateEmail function." Pick a zoom level, draw only that level's concerns, and link to the next level down for those who need it. In practice, most teams get nearly all the value from levels 1 and 2, occasionally 3.

Sequence diagrams

Structure diagrams (like C4) show how the pieces are arranged. Sequence diagrams show how they interact over time — the order of messages between components for a particular flow. They're invaluable for exactly the things that are hard to hold in your head: multi-step flows across services, anything asynchronous, and failure paths.

sequenceDiagram
  actor U as User
  participant API as API Gateway
  participant Ord as Order Service
  participant Pay as Payment Service
  participant Q as Event Bus
  U->>API: Place order
  API->>Ord: createOrder()
  Ord->>Pay: charge() (idempotency key)
  alt payment succeeds
    Pay-->>Ord: ok
    Ord->>Q: publish OrderPlaced
    Ord-->>API: 201 Created
    API-->>U: Order confirmed
  else payment fails
    Pay-->>Ord: declined
    Ord-->>API: 402 Payment Required
    API-->>U: Payment failed, try again
  end

A sequence diagram like this surfaces design questions that prose hides: What happens if the payment succeeds but publishing the event fails? Is charge() idempotent if the user retries? Drawing the flow makes the gaps visible — which is the whole point. Often the act of drawing the diagram catches a bug before any code is written.

Tying it together

These tools aren't paperwork for its own sake — each one is a thinking aid that happens to leave a useful artifact. The RFC exposes holes in a proposal as you write it. The ADR forces you to name consequences, including the bad ones. The C4 diagram forces you to pick an abstraction level and be honest about the shape. The sequence diagram surfaces the failure paths you'd otherwise discover in production. The recorded artifact is a bonus; the clarity the act of creating it forces is the real value.

What this means for you as a lead

Recording the why is where you have outsized leverage, because you're often the only person with the full context of a decision — and that context is exactly what's lost when you're busy, when you move teams, or when new people join. You don't need heavy process; you need a cheap, consistent habit: an ADR for decisions that are hard to reverse or surprising, an RFC for big changes before they're built, and diagrams pitched at a single clear zoom level. Aim for the lightest documentation that lets a competent newcomer understand not just what the system does but why it's shaped this way — because that "why" is what lets them change it intelligently instead of fearfully.