What belongs in an architecture decision record, and how do you decide a decision deserves one?
An ADR captures the context that forced a choice, the options considered with the reason each was rejected, the decision, and the consequences including the costs you accept. Write one when the decision is expensive to reverse or would surprise a future reader, and supersede it rather than edit it.
What the interviewer is scoring
- Does the candidate treat the rejected options as the substance of the record rather than as padding
- Whether the consequences they describe include the costs they knowingly accepted, not only the benefits
- That they understand supersession, and do not describe an ADR as a living document to be kept up to date
- Whether they can state a test for which decisions warrant a record, instead of proposing one for everything
- Does the candidate tie the record to a real audience - the engineer in two years, or the reviewer who was not in the room
Answer
What the record is for
Code tells you what was decided. It does not tell you what the constraints were at the time, which alternatives were live, or what the team knowingly gave up. That reasoning normally lives in a Slack thread, a whiteboard photo and two people's heads, and it is gone within a year of either of them leaving. An architecture decision record is one short document, versioned in the repository next to the code it governs, whose job is to preserve that reasoning for someone who was not in the room.
The audience is specific and it is not your current team: it is the engineer eighteen months from now who finds a choice that looks wrong and needs to know whether it was a mistake or a deliberate trade. Writing for that reader is what keeps the document honest, because it rules out assuming shared context.
The parts, and what each one has to do
Context states the forces in play when the decision was made, in the present tense of that moment. Load figures, team size, deadlines, the existing stack, the compliance constraint, the thing that was already broken. A reader must be able to tell from the context alone why doing nothing was not an option. This section ages into the most valuable part of the document, because it is the only record of a situation that no longer exists.
Options considered, each with the reason it was rejected. Not a list of names — a sentence or two per option saying what it would have cost or failed to give you.
Decision, stated flatly and in the active voice. "We will use X." One decision per record; if you find yourself writing two, you have two ADRs.
Consequences, split between what improves and what gets worse. The second half is the part people skip and the part that matters, because a consequence you wrote down in advance is an accepted cost, and a consequence you did not is a surprise. Six months later that distinction decides whether the team treats a problem as evidence the decision failed or as the bill arriving on schedule.
Status — proposed, accepted, superseded — plus the date and who agreed.
Why the rejected options carry the value
If you keep only the decision, the document tells a future reader nothing they could not infer from the code, and it does not survive contact with a new joiner who says "why aren't we using Postgres for this?" Someone then relitigates the whole thing from scratch, at full cost, usually reaching the same conclusion.
Recorded rejections end that conversation legitimately. Either the reason still holds, in which case the discussion is over in five minutes; or the reason has expired — the throughput assumption changed, the managed service you rejected for lacking a feature now has it — in which case you have a genuine trigger to revisit and you know which premise to re-examine. Neither outcome is available if you only wrote down what you chose.
Immutable, and superseded rather than edited
An ADR is a record of what was decided given what was known then, so editing it destroys the only thing it was for. Once accepted, the text is frozen. Typos aside, you do not update it as circumstances change.
When the decision changes, you write a new ADR that references the old one, and mark the old one superseded with a pointer forward. The pair is more useful than either document alone: the sequence shows how the constraints moved, which is exactly the institutional memory an architecture review needs. A "living" ADR that is quietly rewritten each year is indistinguishable from no record at all, because you can no longer tell what anybody actually believed at the point of commitment.
The test for whether a decision needs one
Two questions, and one yes is enough. Is it expensive to reverse? Anything that shapes a data model, crosses a service boundary, adds a dependency you will build against, or commits you to a vendor. Will it surprise someone later? Anything that looks wrong until you know the reason — an unusual library choice, a deliberately denormalised table, a synchronous call where the house style is asynchronous.
Both questions fail for the vast majority of daily work, and that is the point. Choosing a variable name, adding an endpoint that follows the existing pattern, or picking a test framework the whole company already uses needs no record. A bank of two hundred ADRs is a bank nobody reads; twelve that each explain something genuinely non-obvious gets used. Err towards the surprise test rather than the importance test — small, weird decisions cause more confusion per unit of significance than large, conventional ones.
A record that would earn its place
# ADR 014: Idempotency keys stored in Redis with a 24-hour TTL
Status: Accepted, 2026-03-11. Agreed: payments team, SRE.
## Context
Payment submission is retried by both the mobile client and our own
gateway, so duplicate charges are possible. Peak is roughly 400
submissions/second. The payments Postgres instance is already the
constraint on p99 latency during evening peak. Support has raised four
duplicate-charge tickets this quarter.
## Options
- Unique constraint on a client-supplied key in Postgres. Correct and
durable, but adds a write to the instance we are trying to relieve,
and the table grows unboundedly without a reaper.
- Redis SETNX on the key, TTL 24h. Removes the write from Postgres.
Loses in-flight keys if Redis fails over without persistence.
- No dedupe; reconcile and refund downstream. Cheapest to build, but
the customer sees the duplicate first, which is the actual complaint.
## Decision
Redis SETNX with a 24-hour TTL, key supplied by the client.
## Consequences
- Duplicate submissions inside the retry window are rejected without
touching Postgres.
- We accept that a Redis failover can lose in-flight keys, allowing a
duplicate. At observed retry rates this is a handful per year, versus
four tickets per quarter today. Downstream reconciliation stays as
the backstop and is not removed.
- Clients must now generate and persist a key across retries. Mobile
needs a release; the ADR is linked from that ticket.
- Retries later than 24 hours are treated as new payments. Product
confirmed this is acceptable.
The reason this one works is the second consequence. It names the failure the design permits, quantifies it against the problem being solved, and says the backstop stays. An on-call engineer who sees a duplicate charge next year does not have to guess whether the system is broken.
Where these usually go wrong
The weak version is written after the decision shipped, to justify it. You can spot one immediately: the rejected options are strawmen, and the consequences section contains only benefits. That document has no diagnostic value, because it cannot distinguish a cost that was foreseen and accepted from one that was missed — and telling those two apart is the entire reason anyone opens an old ADR.
The related mistake is writing the ADR at the wrong altitude. An ADR is not a design document. It does not carry the schema, the sequence diagrams or the rollout plan; those live elsewhere and change constantly. It carries one decision and the argument for it, in a page or two, precisely so that it stays short enough to be read and stable enough to be trusted.
Write the ADR while the decision is still uncomfortable, when you can still feel the pull of the option you rejected. Once you are confident, the rejected options have already faded into strawmen and the document is no longer worth writing.
Likely follow-ups
- Someone proposes reversing an ADR from eighteen months ago. What do you do with the original document?
- How do you stop ADRs from being written after the fact purely to justify a choice already shipped?
- Where do ADRs sit relative to an arc42 or C4 document, and what belongs in which?
- How would you handle a decision made by one team that constrains three others?
Related questions
- Every architecture document you have inherited is out of date. How do you write documentation that survives contact with a changing system?mediumAlso on adr4 min
- The business wants to change a rating factor next Monday. Walk me through what actually has to happen.hardAlso on governance5 min
- You discover two teams have independently built notification services that do roughly the same thing. What do you do?hardAlso on governance4 min
- The domain expert tells you one thing and the written procedure says another. How do you work out which one the system should follow?hardAlso on governance5 min
- You have been asked to roll agile out across twelve teams. How would you approach it, and why do most transformations disappoint?hardAlso on governance4 min
- Two senior stakeholders want incompatible things and both outrank you. How do you handle it?mediumAlso on governance6 min
- How do you write a technical strategy that changes what teams do, and get it adopted without authority?hardAlso on decision-records5 min
- How do you choose between a document store, a key-value store, a wide-column store and a graph database for a new service?hardSame kind of round: design5 min