Architecture Decisions and Rationale

Two years after a data platform went live, a new engineering manager asks why order data reaches the warehouse through a nightly extract when the company already runs a streaming platform. Nobody on the current team knows. The engineer who built the extract has moved on, the design document shows boxes and arrows but no reasons, and the only explanation anyone remembers is that streaming was โ€œtoo complex at the time.โ€ The manager now has two poor options. Keeping the design without understanding it may preserve a constraint that no longer exists. Replacing it without understanding it may break something the original designers were protecting.

Michael Nygard described exactly this situation in 2011 when he proposed architecture decision records: without knowing the motivation and consequences of a past decision, a newcomer can only accept it blindly or change it blindly. The diagram was never the missing piece. The reasoning was. This article follows one architecture decision from start to finish: deciding whether it is significant, separating requirements from constraints and assumptions, turning quality goals into testable scenarios, comparing real alternatives, matching the weight of the process to how reversible the decision is, recording it, and knowing when to reopen it.

The running example is invented for illustration. A mid-sized retailer wants order changes from its operational order database available in its analytics platform so that stock and revenue dashboards are no longer a day behind. The figures and judgments in the example are illustrative, not measurements.

Which decisions deserve this treatment

Not every technical choice is an architecture decision, and treating them all as one produces paperwork that nobody reads. AWS’s prescriptive guidance on decision records, drawing on Mark Richards and Neal Ford, lists the kinds of decisions that usually qualify: the structure of the system, non-functional requirements such as security and availability, dependencies and coupling between components, interfaces and published contracts, and construction techniques such as frameworks and processes. Microsoft’s Azure Well-Architected guidance narrows it further to choices that affect the system’s structure or key quality attributes, or that are difficult to reverse.

A practical test combines these. A decision deserves explicit analysis and a record when at least one of the following is true.

  • It is expensive or slow to reverse once other work depends on it.
  • It changes what other teams must build, operate, or agree to, such as a shared interface or data contract.
  • It sets the ceiling on an important quality attribute, such as availability, freshness, or recoverability.
  • It commits significant money, headcount, or a long-term supplier relationship.

The order data decision passes three of the four tests. It creates a dependency between the order system and the analytics platform, it determines how fresh the dashboards can ever be, and whichever mechanism is chosen will soon have many downstream consumers.

Separate needs, requirements, constraints, and assumptions

Decisions go wrong early when a preferred solution is written down as if it were a requirement. โ€œStream order events through Kafkaโ€ is a design choice. The need behind it is โ€œstock and revenue dashboards should reflect recent orders.โ€ The distinction between a need, a requirement, and a design choice is covered in need, requirement, and design choice. Before comparing options, write down four different kinds of input.

InputWhat it isOrder data example
NeedThe outcome someone must achieveMerchandisers can see stock and revenue that reflect recent orders during the business day
RequirementA capability or quality the solution must provideOrder changes, including cancellations and refunds, appear in analytics within a stated time; totals reconcile with the order system
ConstraintA limit the decision cannot changeThe order database is a managed relational service owned by the order team; the company’s approved streaming platform is already in production; no new budget line this year
AssumptionSomething believed true but not yet verifiedThe order team can change its application within two quarters; order volume will roughly double in two years; the database’s change log can be read without affecting checkout

Constraints come in several kinds: technical standards, regulation, budget, deadlines, and the skills of the teams who will build and run the result. Assumptions deserve the most attention because they are where decisions later fail. Each assumption should have someone responsible for checking it and, where possible, a date by which it will be confirmed or dropped.

Turn quality goals into scenarios

A requirement such as โ€œthe pipeline must be reliable and near real-timeโ€ cannot tell options apart, because every vendor and every design claims it. The Software Engineering Institute’s Quality Attribute Workshop method addresses this by expressing quality requirements as scenarios. Its report makes the central point with a modifiability example: saying that the system must be modified to incorporate a new component says nothing about the architecture, since any modification is possible given enough time and money. Adding a response measure, such as completing the change within two person-weeks, is what makes the requirement testable.

The same report asks that each refined scenario describe six things: the stimulus, meaning the condition that affects the system; the source of that stimulus; the artifact affected; the environment or operating condition in which it happens; the response; and the response measure used to judge that response. The environment matters because a response that is easy during quiet hours may be hard at peak load. Here is one scenario for the order data decision.

PartFreshness scenario
Source of stimulusA customer using the storefront
StimulusCancels an order that was placed earlier in the day
ArtifactThe order data path from the order database to the revenue table in the analytics platform
EnvironmentNormal operation during the peak sales hour
ResponseThe cancellation is reflected in the revenue table
Response measureWithin 15 minutes for 99 percent of changes, measured daily. The interval starts when the change commits in the order database and ends when a query against the revenue table returns it. Changes not reflected at all count as failures, not as omissions

The response measure is where most scenarios stay too loose to settle anything. “Within 15 minutes” is only testable once the clock has a defined start and stop, and once someone has said what happens to a change that never arrives. The same discipline applies to the remaining scenarios, which can be written more briefly but not more vaguely.

  • Source load. During the peak sales hour, capturing order changes raises the order database’s average CPU utilization by no more than 5 percentage points above the baseline measured over the same hour on comparable days, and raises checkout’s 99th-percentile latency by no more than 10 milliseconds.
  • Schema change. When the order team adds a column to the orders table in normal operation, analytics ingestion continues without failure, and the new column can be made available within one working day.
  • Recovery. After the ingestion path has been down for four hours, the revenue table matches the order system for that period within one hour of restart, and daily totals reconcile.

The recovery scenario hides a question that has to be answered before any option can be judged against it: does the business need the final state of each order to be correct, or does it need every intermediate change? If a revenue report only needs today’s totals to be right, an option that reads current rows and overwrites is acceptable. If an analyst needs to see that an order was placed, amended twice, and then canceled, an option that reads current rows cannot supply that at all, and no amount of tuning fixes it. The two readings produce different winners, so the scenario is not finished until one of them is chosen. For this example, assume the finance team needs the sequence, because refunds are analyzed by what changed and when.

Scenarios also need an order of importance. The QAW has stakeholders prioritize them before refining the top few. A useful way to rank them is by two questions: how much the business cares, and how hard the scenario is to achieve. A scenario that matters a great deal and is hard to meet is the one most likely to separate the options. In the example, freshness and source load are both high on each count, and they pull in opposite directions.

Generate real alternatives

Consider credible alternatives before committing to a design, including a simpler approach and options raised by people who would bear its costs. Constraints may leave only one viable option; record why the others were excluded and what limitations remain. NASAโ€™s decision-analysis guidance explicitly includes decisions with only one viable alternative. For the order data, three options are initially credible.

  • A. More frequent incremental batch extracts from a replica. Query a read replica for rows changed since the last run, on a short cycle rather than nightly. The cycle length is a variable to be set, not a given, so the option has to be evaluated at the shortest interval the source can sustain. This needs the least new machinery.
  • B. Log-based change data capture. Read the database’s change log with a connector and publish changes to the streaming platform, as described in change data capture. The order application stays unchanged.
  • C. Domain events from the order application. The order service publishes business events such as โ€œorder cancelled,โ€ writing the event to an outbox table in the same transaction as the business change so that the two are stored atomically, as in the transactional outbox pattern. The database transaction records the intent to send atomically with the business change. Delivery still needs a relay that recovers and retries, durable broker acknowledgements, and sufficient retention. Under that delivery contract, repeated messages remain possible, so consumers must prevent duplicate effects and handle the ordering their payload requires.

Each option can be ruled out early if it fails a hard condition. Conditions that an option must meet to be considered at all work differently from preferences among acceptable options, and mixing the two in one score hides failures. Mandatory gates and preferences explains the distinction. In the example, โ€œuses the approved streaming platform or no new infrastructureโ€ is a gate that all three pass.

Evaluate options against scenarios, with evidence

Evaluate each option against each scenario and state what kind of evidence supports each judgment. Evidence ranges from strong to weak: measurements from a prototype or from production, documented behavior of the product in the version to be used, experience from a comparable system, and plain assumption. A judgment backed only by assumption should be marked as such, because it is where a spike or proof of concept pays for itself.

The table below is an illustration, so the evidence column says what evidence would have to be obtained rather than reporting results nobody has measured. In a real decision record, each cell would name the version, configuration, and source: a connector’s documentation section for a specific database and version, the run of a prototype with its parameters, or the system whose production experience is being carried over. “Documented behavior” with no document is an assumption wearing better clothes.

ScenarioA. Incremental batch from replicaB. Log-based CDCC. Domain events
Freshness within 15 minutesDepends on the sustainable cycle, replica lag, and extraction timeSeconds to minutes expected; confirm at peakDepends on relay polling and stream delay
Source load at peak (โ‰ค5 points CPU, โ‰ค10 ms at P99)Replica read load and replication apply must fit the cycleMeasure logging, decoding, storage, and checkout costsMeasure outbox write and index costs on checkout
Schema change without failureDepends on the reader, mapping, and destination contractDepends on connector DDL and schema-history behaviorTable changes stay behind the event contract
Recovery after four hours, sequence preservedFails: current rows cannot recover intermediate changesNeeds retained history and verified catch-upNeeds durable outbox-to-broker delivery and replay
Delivery constraintNo application changeNo application change; log access requiredApplication changes; two-quarter assumption unverified

The comparison turns on different conditions in each row. Follow the same scenario order below to see what must be measured or tested before accepting an option.

Freshness within 15 minutes

A. Incremental batch from replica. Depends on the shortest sustainable cycle. For one change the clock runs: commit at the source, then arrival on the replica, then the wait until the next run that reads it, then extract and load. If a run lasts longer than the scheduling interval, the scheduler must queue, skip, or safely overlap runs; each choice affects delay and resource use. Measure each segment at peak before judging

B. Log-based CDC. Changes are expected to arrive in seconds to minutes. Confirm against the connector’s documentation for the database and version in use, and against its behavior during a peak-hour prototype

C. Domain events. Delay is dominated by the relay’s polling interval and the streaming platform. Confirm with a prototype of the relay

Source load at peak (โ‰ค5 points CPU, โ‰ค10 ms at P99)

A. Incremental batch from replica. Read load moves off the primary, but frequent extracts add read load to the replica and can delay replication apply through resource contention or query conflicts. Measure replica lag under the proposed extraction workload at peak, against the cycle length

B. Log-based CDC. Avoids repeated extraction queries, but additional log generation and decoding still cost resources. PostgreSQL logical logging increases WAL volume, especially with full row images and frequent updates or deletes. Stalled slots can retain storage. Measure CPU, WAL volume, and checkout latency with the intended settings

C. Domain events. Adds an application-level outbox write inside each business transaction. Compare its write and index cost with the database logging cost of CDC; neither is assumed free on the checkout path. Prototype and measure P99 before accepting

Schema change without failure

A. Incremental batch from replica. Compatibility depends on the selected columns, output mapping, and destination contract. An added column can break a positional SELECT * load; renaming an unused column need not affect an explicit-column query. Test the actual reader and writer path

B. Log-based CDC. Table changes propagate, and connectors differ substantially in how they handle DDL and schema history. Read the specific connector’s schema-change section; do not assume that propagation alone keeps downstream ingestion from failing

C. Domain events. Events are a deliberate contract, so table changes do not reach consumers unless the contract changes

Recovery after four hours, sequence preserved

A. Incremental batch from replica. Fails the scenario as written. Reading current rows yields the latest state, not the intermediate changes, so a row amended twice during the outage arrives once. Deletes are also missed unless separately tracked

B. Log-based CDC. Resume from the durable consumer position while all required changes remain available through catch-up, in source logs or a durable downstream stream. Check pre-existing lag, storage limits, and retention at each hop as well as the outage. Verify the one-hour catch-up target, duplicate handling, and order history

C. Domain events. A relay resumes unsent events from the outbox. A consumer resumes durably published events from the broker using its saved position, if broker retention covers the required replay. Outbox rows may be removed after durable acknowledgement unless a separate replay policy needs them. Check catch-up time, duplicates, and ordering across both boundaries

Delivery constraint

A. Incremental batch from replica. No application change

B. Log-based CDC. No application change; needs database log access granted by the order team

C. Domain events. Requires order application changes; relies on the unverified two-quarter assumption

One row settles more than the others. Because the finance team needs the sequence of changes rather than only the final state, option A cannot meet the recovery scenario by being tuned or scheduled more often; it is the wrong shape for the requirement. That is a different kind of elimination from “it might be a bit slow,” and it is worth stating explicitly, because the first kind survives new evidence and the second does not.

Had the requirement been final state only, option A would still be in contention and the freshness row would decide it โ€” which is precisely why that row must be measured rather than asserted. The parts add up differently than intuition suggests: a three-minute cycle against a replica with sub-minute lag leaves most of the 15-minute budget unused, while the same cycle against a replica that falls ten minutes behind at peak spends most of it before the extract even starts, and whether the total still fits depends on how long the extract and load then take. The only way to know is to measure each part under peak load; none of it can be read off an architecture diagram.

Tables like this are often converted into weighted scores. Scores can help structure a discussion, but they produce false precision when the inputs are judgments like โ€œdependsโ€ and โ€œexpected.โ€ If you do score, follow the discipline in weighted scoring and test the result with sensitivity analysis, which asks whether plausible changes in weights or inputs would change the ranking.

The more valuable output of the evaluation is a short list of deciding assumptions: beliefs that would change the choice if they turned out to be false. In the example there are three.

  • If finance needs only the final state of each order rather than the sequence of changes, option A returns to contention, and the decision turns on measured freshness instead.
  • If the order team cannot change its application within two quarters, option C is not available in time.
  • If the database’s change log cannot be retained long enough to cover a realistic outage, option B’s recovery scenario fails.

The first assumption is the cheapest to check and the most consequential: ask finance what they do with the data, and look at whether any existing report distinguishes an amended order from a canceled one. Checking it before building anything may remove most of the decision. The others need a configuration check and a conversation with another team’s lead, whose effort depends on access to the relevant settings and people; they can begin before implementation.

Name the trade-off you are accepting

Suppose the merchandisers confirm that 15 minutes matters and the order team’s roadmap is full for the next year. The evaluation now favors option B. Choosing it is not only a matter of what it provides. It also accepts specific costs, and the decision should say so plainly.

  • Coupling to the table structure. In this example, the source team has not yet committed to a compatible published schema or change-notification process. Internal refactoring can therefore break analytics. CDC can operate under an explicit data contract; adopting one would reduce this risk without changing the capture method.
  • New operational responsibility. Someone must run the connector, watch log retention, and handle restarts. The decision has to name that owner.
  • Deferred semantics. The change log records row changes, not business meaning. โ€œOrder cancelledโ€ has to be inferred from status columns, and that inference becomes analytics logic that the order team does not see.

Naming the accepted costs does two things. It lets people who would bear those costs object before the decision is final, and it tells a future reader which problems were anticipated and which were surprises.

Match the process to how reversible the decision is

Jeff Bezos’s 2015 letter to Amazon shareholders separates two kinds of decisions. Some are consequential and irreversible or nearly so, which he calls one-way doors or Type 1 decisions, and they deserve slow, careful deliberation and consultation. Most decisions are reversible two-way doors, Type 2 decisions, which small groups or individuals with good judgment can and should make quickly. His warning was that large organizations tend to apply the heavy Type 1 process to Type 2 decisions as well, which makes them slow, risk-averse, and less inventive.

The distinction applies directly to architecture, with one refinement: reversibility changes over time. A decision that is a two-way door today can become a one-way door once enough systems depend on it.

Usually a two-way doorUsually a one-way door, or becomes one
The schedule of a batch jobA published event schema or API consumed by many teams
A library used inside one serviceThe authoritative source for a core business entity
The instance size of a managed databaseA multi-year supplier contract or a proprietary data format that holds years of history
An internal module boundary within one team’s codeWhere regulated data is stored, and in which jurisdiction

Spend deliberation where the door is one-way and let teams decide two-way doors quickly, recording only the ones that affect others. Before committing, look for ways to make a one-way door more reversible before walking through it: put a deliberate interface between consumers and the underlying mechanism, keep the old path running during a migration, roll out to one consumer first, and write an exit plan before signing a long contract. In the example, the biggest one-way risk in option B is downstream reports binding to the raw table structure. Publishing a curated order change table in the analytics platform, and asking consumers to use it rather than the raw feed, keeps the door partly open. If the order team later adopts domain events, the curated interface can shield report queries from the new ingestion path only if those events can reproduce its grain, identifiers, meaning, and required change history. Establish a cutover boundary, reconcile outputs, and handle duplicates or missing history through mapping and backfill where needed. A narrower event feed may not satisfy the existing contract at all.

Record the decision

An architecture decision record captures a decision while its reasoning is still fresh. Nygard’s original format has five parts: a short noun-phrase title, the context describing the forces at play, the decision stated in active voice, a status such as proposed or accepted, and the consequences, including negative and neutral ones. He suggested keeping each record to one or two pages, numbering records sequentially without reusing numbers, and keeping reversed decisions marked as superseded rather than deleting them.

Later guidance adds practices worth adopting. Microsoft recommends recording the options that were ruled out, the important trade-offs, and the confidence level of the decision, since a decision made with low confidence is a natural candidate for early review. It treats the collection of records as an append-only log, so an accepted record is never edited and a changed decision gets a new record that links to the old one. It also suggests writing records retroactively for existing systems when the history is known, and splitting a decision into several records when it will be carried out in phases. AWS describes a review in which a record starts as proposed, and the review meeting opens with 10 to 15 minutes of silent reading so that discussion starts from a shared understanding.

A record for the example might look like this. Two fields go beyond the minimum format and earn their place: the deciding assumptions and the review triggers.

ADR 14: Capture order changes with log-based CDC

Status: Accepted (supersedes ADR 6: Nightly order extract)
Decided by: Analytics platform lead and order service lead
Level: Solution (affects order system, analytics platform, finance reporting)
Confidence: Medium

Context
  Merchandisers need stock and revenue reflecting orders within 15 minutes
  during the business day. Finance analyzes refunds by what changed and
  when, so the sequence of changes is required, not only the final state.
  The order team cannot change its application in the next 12 months.
  The approved streaming platform is in production.
  Scenarios:
    Freshness - 99% of committed order changes queryable in the revenue
      table within 15 min, measured daily; commit to first successful read.
      For batch options this budget runs from source commit through
      replica arrival, the wait for the next run that reads the change,
      and the extract and load.
    Source load - at peak hour, +5 percentage points or less on order DB
      average CPU vs same-hour baseline; +10 ms or less on checkout p99.
    Schema change - added column does not fail ingestion; available in
      one working day.
    Recovery - after a 4-hour outage, revenue table matches the order
      system for that period within 1 hour of restart, sequence preserved,
      daily totals reconcile.

Options considered
  A. Incremental batch extract from replica, shortest sustainable cycle -
     rejected on shape, not tuning: reading current rows returns the latest
     state, so intermediate changes during the outage window are lost and
     the recovery scenario cannot be met at any cycle length.
  B. Log-based CDC to streaming platform - chosen.
  C. Domain events via transactional outbox - rejected for now: requires
     order application changes not possible within 12 months.

Decision
  We will capture order table changes with a CDC connector and publish a
  curated order change table in the analytics platform. Downstream reports
  will read the curated table, not the raw change feed.

Consequences
  + Freshness and source load scenarios expected to be met, pending the
    verification below.
  - Analytics depends on the order database's table structure.
  - Analytics platform team operates the connector and monitors log retention.
  - Business meaning (for example, cancellation) is inferred in analytics.

Deciding assumptions
  Finance requires the sequence of changes, not only the final state.
  Database log retention can be set to at least 24 hours.
  Order volume roughly doubles in two years, within connector capacity.

Open verification (accepted at medium confidence on this basis)
  Owner: analytics platform lead. Due: before production cutover.
  V1 Peak-hour prototype: measure source CPU delta and checkout p99 delta
     against the scenario limits.
  V2 Confirm the connector's documented schema-change handling for our
     database version; test an added column end to end.
  V3 Replay a 4-hour backlog and measure catch-up time, duplicates, and
     ordering within an order key.
  V4 Measure commit-to-query visibility at peak and across daily populations.
     At least 99% of committed changes must be visible within 15 minutes
     each day; count changes still missing after their deadline as failures.
  Cutover requires V1, V2, V3, and V4 to pass. If any fails, block cutover
  and revise the implementation or reopen the decision; do not silently
  relax a required scenario.

Review triggers
  Order team gains capacity for domain events.
  Any schema change breaks ingestion twice in a quarter.
  Any daily freshness target miss triggers investigation. Repeated misses
  over a week trigger architectural review; the review window does not
  change the daily acceptance target or exclude undelivered changes.

The last block is what makes an accepted record honest when parts of it are still unverified. Accepting a decision before every measurement is often correct, because some measurements only become possible once work starts. What is not acceptable is letting the record read as though the measurements were already taken. Naming an owner, a deadline, and what happens if a check fails keeps the difference visible.

A record written after the fact to justify a decision, or one that lists only benefits, does specific damage rather than merely being useless. It tells a later reader that alternatives were weighed when they were not, so that reader does not reconsider them. It presents an assumption as a finding, so nobody goes back to test it. And when the omitted drawback finally surfaces, the record gives no clue whether it was accepted knowingly or never noticed, which is the one thing the reader needs in order to decide what to do next. The test is whether a skeptical engineer two years from now could see what was known, what was guessed, and what was given up.

Revisit when assumptions change

Decisions age. The context that made option B right can change, and the record should make that change noticeable instead of leaving it to someone’s memory. Review triggers do this by naming observable conditions that should reopen the decision, as in the example above. They are more useful than a calendar reminder because they point at the specific assumption that failed.

Some triggers can be checked automatically. Thoughtworks’ Technology Radar describes architectural fitness functions, a term taken from the book Building Evolutionary Architectures: automated assessments of architectural characteristics that can reuse ordinary tests, metrics, and monitors so that those characteristics are validated continually rather than only at design time. For the order data decision, a fitness function could be a monitor that alerts when end-to-end lag exceeds the freshness scenario, or a test that fails when a new report reads the raw change feed instead of the curated table.

A trigger firing is a reason to look, not a verdict. Conflating the two produces a stream of superseding records for decisions that never actually changed. The sequence has four steps.

  • The condition occurs. Lag exceeds the freshness scenario for a week, or the order team frees up capacity.
  • Find the cause and check the assumption behind it. Lag may come from a connector setting, a load increase the capacity assumption did not anticipate, or a downstream consumer that slowed down. These lead to different conclusions.
  • Decide whether the original choice still holds. Often it does, and what is needed is tuning, more capacity, or a corrected assumption. Sometimes the assumption that justified the choice is simply gone.
  • Write a new record only if the decision changes. AWS’s guidance describes superseding this way: a new judgment calls for a different decision, and the old record is superseded when the new one is accepted. Where the decision stands, note the review and its outcome without superseding anything, so the next reader can see the question was asked and answered.

Whichever way it goes, the record is never edited in place; the log is append-only, and a decision that changed gets a new record linked to the old.

It also helps to separate the quality of a decision from the quality of its outcome. A decision made with the information and uncertainty that existed at the time can be sound even if events later make it the wrong choice. Reviews that treat every bad outcome as a bad decision teach teams to avoid recording their reasoning.

Common ways the process fails

  • Decided before analyzed. A product demo or a team’s enthusiasm settles the choice, and the analysis is assembled afterward to support it. The sign is an options section with one serious option.
  • Heavy process for two-way doors. Every choice goes to a review board, reviews queue up, and teams either wait or quietly stop asking.
  • Light process for one-way doors. A team adopts a new database or identity mechanism for one system, others start depending on it, and a company-wide commitment is made without anyone deciding it.
  • No owner for consequences. The record lists new operational work but nobody accepted it, so it falls to whoever is paged first.
  • Decisions never revisited. Records exist but have no triggers, so a decision outlives the constraint that justified it, which is exactly the situation in the opening story.

References


Discover more from Insightful Data Lab

Subscribe to get the latest posts sent to your email.

Similar Posts

Questions, corrections, or additional insights?

This site uses Akismet to reduce spam. Learn how your comment data is processed.