Decisions, diagrams and reviews
An architecture lives in people's heads until you write it down. This lesson gives you four tools that keep it alive as the system and the teams grow: ADRs that record why, C4 diagrams that show what, reviews that find the trade-offs, and fitness functions that check the decisions on every build.
By the end you can
- Decide which decisions deserve an ADR, and write one in the MADR format with drivers and a confirmation
- Draw C4 context, container and component diagrams that a new engineer can read without you
- Run a scenario-based review and sort its findings into risks, non-risks, sensitivity points and trade-off points
- Turn an ADR into fitness functions that run in CI and fail the build when the decision is broken
- Set up light governance: who decides, who must be asked, and when a decision is revisited
The everyday picture
Think of an old building that changes owners every few years. A good building keeps three things in a cupboard by the door. A set of maps at different zoom levels: the street, the floor plan of each storey, and the wiring of one room. A logbook that says why things are the way they are: "the stairs are here because the fire code needs two exits". And an inspection record, plus smoke detectors on every ceiling that check all day, every day.
A new owner who finds that cupboard can change the building safely. A new owner who finds it empty knocks down a wall that was holding up the roof. Your software has the same cupboard. C4 diagrams are the maps, ADRs are the logbook, reviews are the inspections, and fitness functions are the smoke detectors.
Which decisions earn an ADR
If every small choice gets an ADR, nobody reads them. If only the big rewrite gets one, the decisions that hurt you most are never written down. You need a test. An architecturally significant decision is one that changes the structure of the system or one of its quality attributes, and is expensive to change later. A practical test has four questions. Answer yes to any one and write an ADR:
- Cost of change. Would undoing it later take more than about one engineer-month? At Mangrove an engineer costs about $5,000 a month, so that is a decision worth about $5,000 or more to reverse.
- Quality attribute. Does it help or hurt one of your measured scenarios, such as receiving speed or partner price freshness?
- Team boundary. Does it change what another team, or an outside agency, has to build or run?
- New technology. Does it add a language, a data store, a broker or a cloud service that someone must operate at 3 am?
The basic ADR from Running a design review has context, decision and consequences. Architects get more value from the richer MADR template (version 4.0 at the time of writing). Three of its sections do the heavy lifting. Decision drivers list the forces behind the choice; write each one as a link to a scenario ID, so the ADR is tied to a measured need instead of a taste. Considered options must hold at least two real alternatives with their pros and cons. Confirmation says how you will know the decision is being followed, which is where fitness functions come in later in this lesson.
A good ADR also fits in one sentence. Olaf Zimmermann's Y-statement gives the shape: "In the context of month-end stock reports, facing receiving freezes, we decided for a read replica and against query tuning, to achieve receiving under 2 seconds at p95, accepting data up to 15 minutes old." If you cannot write that sentence, the decision is not clear yet.
Finally, keep the log healthy. Each ADR has a status: proposed, accepted, rejected, deprecated, or superseded by a later number. Keep one decision per file, numbered, in docs/adr/ next to the code. Add an index file that lists every ADR with its status, so a reader can see the current architecture in two minutes.
Quick check
Which of these decisions most clearly deserves an ADR?
The Partner app change crosses a team boundary (Lagoon Digital builds that app), changes data freshness, and would cost weeks to reverse. The other three are cheap to undo and touch no quality attribute, so a pull request note is enough. Formatting matters, but a linter config records it better than an ADR.