Skip to main content

Someone wanted to learn this too, so Grasp built them a personal learning path.

You can keep exploring this one or create your own

Writing Effective Architecture Decision Records

Hello again. The last lesson compared direct delivery to a reporting API with a durable asynchronous channel. It established what each option must prove, but deliberately stopped short of choosing one. This lesson turns that comparison into an architecture decision record (ADR): a document that tells another engineer what was chosen, why it made sense under the circumstances, what was given up, and what the teams must now do.

The invoice pilot remains our working case. The example ADR below makes a proposed choice rather than claiming that tests or approvals have already happened. That distinction matters: a clear recommendation can be written before it is accepted, provided the record is equally clear about what remains unverified.


Record the decision at a particular moment

An ADR is not a description of the system as it exists forever. It records a consequential choice in its decision context. If reporting capacity, the pilot deadline, or the available platform services change, a future team needs to know which assumptions supported the original choice before deciding whether to keep it.

Watch the opening of CodeOpinion’s Architecture Decision Records (ADR) as a LOG that answers “WHY?”. It explains why the circumstances behind a decision can be as valuable as the decision itself.

Architecture Decision Records (ADR) as a LOG that answers "WHY?"

CodeOpinion’s “Architecture Decision Records (ADR) as a LOG that answers ‘WHY?’” introduces ADRs as a way to preserve the reasoning that code alone cannot reveal.

Watch the motivation for recording the conditions under which a choice was made. Then watch the basic structure: title, context, decision, status, and consequences. Notice that consequences include unfavorable outcomes, not just benefits.

The diagram below offers a fuller set of fields. Read its boxes as parts of a record, not as a prescribed order for making decisions: the decision’s context and options must be understood before its consequences can be judged.

An ADR template showing an identifying title, dates and status, context, the chosen decision, options and trade-offs, consequences, and links to related records or standards. Together these fields preserve both the choice and the conditions behind it.

A useful ADR stays focused on one decision boundary. For our pilot, that boundary is the handoff from invoice intake to reporting—not the entire reporting architecture. The record should give a reader enough information to reconstruct the choice without copying the full evaluation from the previous lesson.


Make the reasoning visible, not merely the answer

Before drafting our ADR, look at a completed example. AWS Prescriptive Guidance’s Appendix: Example ADR is about a development workflow, not invoice processing, but its organization illustrates a direct decision statement and both positive and negative consequences.

Appendix: Example ADR - AWS Prescriptive Guidance

Read AWS Prescriptive Guidance’s example to see how a specific choice is distinguished from the reasons for it and from the work it imposes.

On the “Appendix: Example ADR” page, first glance at “Title,” “Status,” and “Date.” Then, beginning in “Context” with “ABC application is a packaged solution,” read Context through Compliance. Stop at the end of “Compliance,” before “Notes.” Focus on the explicit “We use” decision, the acknowledged overhead under “Consequences,” and the concrete checks under “Compliance.”

The AWS example makes a distinction worth carrying into our case. Rationale explains why one option was selected relative to the alternatives and decision criteria. Consequences describe what becomes true, or what work becomes necessary, because that option was selected. “We chose direct delivery because an existing reporting API can be validated within the pilot schedule” is a rationale—but only if that API and schedule advantage are confirmed. “Intake must retain and monitor pending deliveries during reporting outages” is a consequence of implementing the choice.

Avoid sentences that collapse these categories into a slogan: “Use a queue for scalability” neither establishes a measured need nor explains the cost, ownership, or failure handling of a queue. Likewise, “Use the API because it is simpler” conceals the retry mechanism and operating burden that may make it anything but simple. Strong ADR language names the relevant condition and its evidential status.

A compact record for the invoice handoff needs to answer four questions:

  1. What problem and constraints existed? State the 95% within 15 minutes searchability objective, the acceptance-to-searchability boundary, the pilot scope, and the security and delivery constraints that must be confirmed.
  2. What options were seriously considered? Name direct API delivery with persisted retry and a durable asynchronous channel. Give the principal reason for preferring one without reproducing every comparison row.
  3. What exactly is being decided, and at what status? Say whether the text is a proposal or an accepted choice. Specify the scope of the decision so an implementation team cannot mistake it for approval of every downstream design detail.
  4. What follows from it? Record benefits, costs, risks, required safeguards, owners to confirm, and evidence that would require reconsideration.

Draft a decision another team could implement

Here is a worked, illustrative ADR. It selects direct delivery for the pilot, conditional on evidence that has not yet been supplied. Its proposed status is intentional; neither the existence of a suitable API nor successful joint tests should be invented to make the document sound decisive.

# ADR-___: Deliver pilot invoices to reporting through its API

Status: Proposed
Decision date: Pending approval
Decision makers: Intake and reporting technical owners, with the relevant
product and security approvers to be confirmed
Scope: Invoice intake-to-reporting handoff for the enterprise pilot

## Context

The pilot objective is for at least 95% of submitted invoices to be
searchable within 15 minutes. Product must confirm the submission event,
measurement window, denominator, and authorized query used to verify this.
An accepted invoice must remain discoverable and recoverable even if it
misses the time target.

Intake and reporting are separately owned. Reporting availability, bursts,
duplicate delivery, tenant isolation, and investigation of missing invoices
affect this handoff. Applicable security controls and pilot delivery limits
require confirmation by their owners.

## Options considered

1. Direct delivery to a reporting-owned API, with intake durably recording
   pending deliveries and retrying failures.
2. A durable asynchronous channel, with a safe acceptance-to-publication
   mechanism and a reporting consumer.

Both options still require reporting to handle duplicates, validate tenant
identity, and demonstrate the full path to searchability. Neither removes a
reporting capacity bottleneck.

## Decision and rationale

For the pilot, we propose direct API delivery with persisted retry. Intake
will commit the accepted invoice and its pending-delivery state durably
before treating submission as accepted. Reporting will define what an API
acknowledgment means; it will not be treated as proof of searchability.

This is preferred only if reporting confirms that a suitable API can be
provided and supported for the pilot, and joint testing demonstrates
acceptable recovery and end-to-end timeliness. Under those conditions,
reusing that integration avoids introducing and assigning ownership of a
new channel and consumer for the pilot. This is a delivery rationale, not
a claim that direct delivery is inherently more reliable or less costly.

If the API, durable pending state, or joint validation cannot meet the
confirmed gates and limits, this proposal must be revisited. The channel
option remains viable; it is not rejected as an architectural pattern.

## Consequences and trade-offs

Positive: The pilot can use an agreed reporting API contract without
introducing a new channel and consumer, provided the assumed API is
available. The handoff remains explicit at the service boundary.

Negative: Intake owns pending-delivery storage, retry scheduling, and
visibility into failed or aging deliveries. Reporting outages can grow
that pending workload. The teams must agree on recovery authority and
the contract for ambiguous timeouts and duplicate requests.

Required safeguards: Reporting must validate service and tenant identity
and handle repeated delivery safely. The teams need a shared invoice
correlation key, alerts for aging pending work, a repair path for stuck
invoices, and a way to verify searchability through an authorized query.
Applicable audit and data-handling controls require security review.

## Confirmation and review

Before acceptance, the responsible owners must confirm the API contract,
security requirements, cost and support implications, and pilot limits.
Joint tests must cover a representative burst, a reporting outage, an
intake process crash, a timeout with uncertain delivery, and a duplicate.
Measure submission-to-searchability for individual invoices, not just
API acknowledgments; agree how missed invoices are found and recovered.

Revisit this ADR if the API is unavailable, recovery tests fail, the
confirmed timeliness objective is not met, or the pending workload becomes
unsupportable. Record a subsequent decision if the handoff changes.

The first sentence of Decision and rationale gives an implementable direction. The qualifying paragraphs prevent it from masquerading as an approved result. That is preferable to either a vague “we may use an API or a channel” or an unjustified “the API meets the target.”

Notice also what the record does not decide. It does not pick retry intervals, a Java library, or an alert threshold without evidence. Those details need owners and validation, but they do not all need to be smuggled into this handoff decision. Conversely, omitting the need for durable pending state would make “direct delivery with retry” misleading: it is central to the option being chosen.


Keep the record useful after the meeting

An ADR should support approval, implementation, and later re-evaluation. Reviewers should be able to challenge a statement at the right level. Product can resolve what “submitted” and “searchable” mean. Reporting can confirm its API semantics and duplicate handling. Security can review tenant checks and audit evidence. Intake and reporting can agree who detects, repairs, and explains a stuck invoice. The Tech Lead’s job is to make those boundaries explicit, not to mark unresolved approvals as complete.

Once a decision is accepted, retain the historical reasoning rather than silently rewriting it to fit later events. Update status and link a new decision if a changed circumstance calls for a different handoff. The original ADR then still answers its most valuable question: why was this reasonable when we chose it?

Before considering a draft ready, check it for three common failure modes. First, can a reader identify the chosen option in one sentence? Second, can they distinguish verified facts from assumptions and pending tests? Third, do the negative consequences name real work and ownership rather than merely saying “adds complexity”? If any answer is no, tighten the record before asking others to approve it.


Conclusion

A useful ADR is a concise, dated account of a choice, its context, its comparative rationale, and its consequences. For the invoice pilot, the proposed direct-API choice is clear without pretending that the API or its recovery behavior has already been validated. The record preserves the channel alternative, makes trade-offs explicit, and states what must be confirmed before acceptance.

This closes the module on setting technical direction. The next module begins with turning a chosen direction into incremental delivery: small slices that provide value while testing the uncertainties the ADR has made visible.

Can't find a good explanation? Sign up and we'll make it for you

Sign up