Leer en español · Lire en français · Auf Deutsch lesen
Section 1.6 of 1.8 · Intermediate · 20 min read
Architectural decisions and trade-offs: reversibility and timing
Video lesson
5 min · narrated, with captionsListen only (audio)
Read the transcript
Architects make decisions all the time, and none of them come free. This lesson covers how to weigh trade-offs, which decisions deserve care, when to decide, and how to show your reasoning.
Choosing a car is a trade-off. A bigger engine costs more fuel; a smaller car is easier to park but carries less. Nobody gets everything. Some choices are easy to undo, like a paint colour you can change later. Others, like buying the house next to a motorway, are very hard to undo. Good architects make the easy choices quickly, take care over the hard ones, decide at the right time, and write down why.
Mark Richards and Neal Ford's first law: everything in software architecture is a trade-off. Caching buys speed and pays in staleness. If you think you've found something that isn't a trade-off, you probably haven't spotted it yet. Their second law: why is more important than how. Anyone can see how a system is built. What the code can't tell you is why: which alternatives were considered, and which risks were accepted. And a third: most decisions aren't binary. You rarely choose between a monolith and microservices; you choose how many deployable units, split along which lines.
A well-formed decision has six parts. On the left are three inputs: the context, meaning the forces and constraints; at least two real options; and the criteria, drawn from stakeholder concerns. They feed the decision itself, and its rationale: why the chosen option beat the others. Then the consequences, meaning the gains, costs, risks and options now closed, and the status, such as proposed, accepted or superseded. Notice the dashed arrow. Consequences become context for later decisions. Choose asynchronous messaging, and next you must decide how to handle duplicate messages.
The most useful property of a decision is how cheaply it can be undone. Jeff Bezos called reversible decisions two-way doors. Make them quickly, in small groups, because you can walk back through. A logging library behind your own interface is one. One-way doors are nearly irreversible, like the data model of a system of record, or a public API that hundreds of partners use. They deserve slow, careful deliberation with the people who bear the consequences. And reversibility shifts over time. The more code, data and people depend on a choice, the harder it becomes to undo.
So when should you decide? As a project goes on, what you know rises, while the options still open fall. Decide too early, and you're guessing. Fixing the database in week one, before you understand the shape of the data, is a guess. The last responsible moment is the point where failing to decide would remove an important option. Deciding then uses the most knowledge, without letting the decision be made for you. Leave it too late, and the decision is made by default, for example when code has already been written around an unspoken assumption. This isn't a licence to procrastinate. Know which decisions are pending, when each must be made, and use the time before then to learn.
Here's a worked example. A food delivery company needs a database for a new order service. Payments must never be lost or double-charged. The team of six knows PostgreSQL well, but has no database administrator. There are three options: a managed PostgreSQL service, the cloud provider's own document database, or PostgreSQL that the team runs itself. They agree six criteria and their weights first, such as transactional integrity and operational effort, then score each option. Managed PostgreSQL scores seventy nine out of ninety five, ahead of seventy three and sixty seven. Then a sensitivity check: what if growth were far higher, or someone else ran the databases? Option A stays first or joint first. The result hinges mainly on the team's lack of database operations capacity. So they choose managed PostgreSQL and record the downsides honestly: a higher monthly bill, and maintenance windows set by the provider. The numbers don't make the decision; they make the reasoning visible.
Because the why matters most, it has to be written down. The usual format is an Architecture Decision Record, or ADR: a short text file with a title, status, context, decision and consequences. It's kept with the code, and never edited to change history. A later decision supersedes it and links back, so the log tells the story. And avoid the common mistakes: considering only one option, hiding the downsides, and never revisiting a decision when its assumptions change.
That's decisions and trade-offs. The full section has a guide to deciding now or later, the cognitive traps to watch for, and a sample ADR. Next, in Section one point seven, we look at technical debt. See you there.
What you need to know
- Every significant architectural choice is a trade-off: it improves some qualities at the expense of others, and the downsides must be found and stated.
- A well-formed decision records its context, the options considered, the criteria, the decision with its rationale, the consequences and its status.
- Reversibility is the key property of a decision: two-way doors should be decided quickly and locally, one-way doors deliberately and with the people who bear the consequences.
- The last responsible moment is the point at which delay would remove an important option; deciding then uses the most knowledge without letting the decision be made by default.
- Abstractions at boundaries, feature flags, incremental migration and spikes make decisions more reversible, at a cost worth paying only where uncertainty and reversal cost are both high.
- Weighted decision matrices and Architecture Decision Records make reasoning visible and open to challenge; agree criteria and weights before scoring, and test how sensitive the result is to them.
Everything is a trade-off
Every significant architectural choice buys something by giving something else up. Splitting a system into independently deployable services buys team autonomy and independent scaling, and pays in network latency, operational complexity and harder data consistency. Caching buys speed and pays in staleness and invalidation logic. A managed cloud database buys freedom from patching and backups and pays in cost and dependence on one provider. Mark Richards and Neal Ford put this at the head of Fundamentals of Software Architecture (2020; second edition 2025) as their first law: Everything in software architecture is a trade-off.
A corollary they draw is that if you think you have found something that is not a trade-off, you have probably not yet identified the trade-off.
Their second law is that why is more important than how. Anyone can look at a running system and see how it is built: three services, a message broker, a document database. What cannot be recovered from the code is why: which alternatives were considered, which concerns won, which risks were accepted. Without the why, later engineers either preserve choices that no longer make sense or undo choices whose reasons still apply. The second edition adds a third law: most architectural decisions are not binary but sit on a spectrum between extremes. You rarely choose between "monolith" and "microservices"; you choose how many deployable units, split along which lines, sharing what.
Thinking in trade-offs is the habit that most clearly separates architectural thinking from enthusiasm. When someone proposes a technology, the useful questions are not "is it good?" but "what does it cost, what does it make harder, and are those costs acceptable given our concerns?" The previous section showed where those concerns come from.
The anatomy of a decision
An architectural decision is more than its outcome. A decision that can be explained, reviewed and revisited has six parts, and naming them is the first step to making decisions well.
Context: the forces at play. The problem being solved, the quality attribute requirements that bear on it, the constraints (budget, deadlines, regulations, existing systems, team skills) and the assumptions being made. Options: at least two genuine alternatives, often including "do nothing" or "defer". A decision with only one option considered is an announcement, not a decision. Criteria: how options will be judged, derived from stakeholder concerns and weighted by importance. Decision and rationale: the option chosen and, crucially, why it beat the others on the criteria. Consequences: what becomes easier, what becomes harder, what new risks appear, and which future options are now closed. Status: proposed, accepted, deprecated or superseded, plus who made the decision and when.
Consequences deserve particular attention because they are where honesty is tested. Every option has downsides; writing them down protects the team from surprise and gives the next decision-maker a fair account. The consequences of one decision also become part of the context for the next: once you have chosen asynchronous messaging, you must decide how to handle duplicate and out-of-order messages.
Anatomy of an architectural decision
One-way doors and two-way doors
The most useful single property of a decision is its reversibility: how cheaply and safely it can be undone. In his 2015 letter to Amazon shareholders, Jeff Bezos distinguished Type 1 decisions, which are consequential and irreversible or nearly so ("one-way doors"), from Type 2 decisions, which are changeable and reversible ("two-way doors"). Type 1 decisions deserve slow, careful deliberation and consultation. Type 2 decisions should be made quickly by individuals or small groups with good judgement, because if they turn out wrong you can walk back through the door. His warning was that large organisations tend to apply the heavyweight Type 1 process to everything, which makes them slow and timid.
The idea translates directly into architecture. A one-way door in software is a decision that would require rewriting large parts of the system, migrating large amounts of data, renegotiating contracts or retraining many people to undo: the primary programming language of a large codebase, the data model of a system of record, the public API that hundreds of partners integrate with, a multi-year cloud commitment. Two-way doors include the choice of a logging library behind your own interface, the internal structure of one module, the tuning of a cache, or which of two equivalent message formats to use inside one service.
Two cautions. First, reversibility is a spectrum, not a binary: most decisions sit somewhere between "trivial to undo" and "impossible to undo", and the cost of reversal usually grows as more code, data and people come to depend on the choice. A decision that is a two-way door in month one can become a one-way door by month twelve. Second, you can often change which kind of door you are facing, by design, as the section on reversibility below shows.
Timing: the last responsible moment
When should a decision be made? Mary and Tom Poppendieck, in Lean Software Development: An Agile Toolkit (2003), popularised the idea of deciding at the last responsible moment: the moment at which failing to decide would eliminate an important alternative. Before that moment you are deciding with less information than you could have; after it, the decision is made for you by default, usually badly.
The principle cuts both ways. It argues against deciding too early: fixing the database technology in week one, before you understand the data's shape and access patterns, is guessing. It equally argues against deciding too late. If the team has started writing persistence code against an unspoken assumption, the decision has already been made, just not consciously. If procurement needs six weeks to approve a cloud provider, the last responsible moment for that choice is at least six weeks before you need the environment.
Practitioners disagree about how far to push this. Critics point out that "last responsible moment" is easily misused as a licence to procrastinate, that some decisions (team structure, programming language) shape everything that follows and so must be made early, and that indecision has its own cost: teams cannot work in parallel without agreed interfaces. Advocates reply that the principle never meant "as late as possible" but "as late as is responsible", and that identifying the moment is itself an act of planning. Both positions agree on the practical core: know which decisions are pending, know when each must be made, and use the time before then to learn.
Deciding too early, too late and at the right time
Designing for reversibility
The cheapest way to make a hard decision is often to turn it into an easier one. Several techniques lower the cost of changing your mind later, at the price of some effort now.
Abstraction at the boundary. Put a narrow interface of your own between your core logic and a technology you might replace, such as a payment provider, a message broker or a large language model API. Swapping the technology later then touches one adapter instead of the whole codebase. The idea goes back to David Parnas's information hiding (1972) and reappears in hexagonal architecture (Chapter 5). Feature flags. Ship new behaviour switched off, turn it on for a small share of users, and switch it off again in seconds if it misbehaves; this makes releases two-way doors. Incremental migration. Run old and new side by side and move traffic gradually rather than switching in one step. Spikes and proofs of concept. Spend a few days building the riskiest part with a candidate technology before committing to it. Contractual exits. Prefer shorter commitments, standard data formats and the ability to export your data.
This is options thinking, borrowed from finance: you pay a small premium now (an adapter, a flag, a spike) to buy the right, but not the obligation, to change course later. Like any option, it is only worth buying when the premium is small relative to the value of the flexibility. Wrapping every library in an abstraction "in case we change it" is a classic way to add cost and indirection for flexibility nobody uses. Buy options on the decisions that are both uncertain and expensive to reverse; for everything else, decide and move on.
Decision guide
Decision guide: decide now or defer?
Use this for any decision that might be architecturally significant. Work down the questions in order.
- Is other work blocked, or will an important option disappear soon if nobody decides (for example a procurement lead time or a team starting to build on an assumption)?YesYou are at the last responsible moment. Decide now with the information you have, record the decision and its assumptions, and set a date to review it.NoGo to the next question.
- Is the decision cheap and safe to reverse (a two-way door)?YesDecide quickly, at the lowest sensible level (often by the team that owns the code), record it briefly and move on. Do not spend a week debating it.NoIt is a one-way door. Go to the next question.
- Can you cheaply make it more reversible, for example with an interface around the technology, a feature flag or an incremental migration path?YesBuy that option first, then treat the remaining decision as a two-way door.NoGo to the next question.
- Would information you can realistically obtain before the deadline (a spike, a load test, a conversation with a stakeholder) change the choice?YesDefer deliberately: name the decision, the owner, the date by which it must be made and the experiment that will inform it.NoMore waiting will not help. Run a structured comparison now (criteria, weights, options), involve the stakeholders who own the consequences, and write an Architecture Decision Record.
Cognitive traps
Architects are human, and architectural decisions are made under uncertainty, time pressure and social pressure: ideal conditions for cognitive biases. Knowing the common ones by name makes them easier to catch in yourself and to challenge kindly in others.
Traps that distort architectural decisions
| Trap | What it looks like | Countermeasure |
|---|---|---|
| Anchoring | The first option mentioned, or the first estimate given, becomes the reference point that every other option is judged against. | Generate several options independently before discussing any; ask people to write estimates down before sharing. |
| Sunk cost | "We have spent eight months on this framework, we cannot drop it now", even though the past spend is gone whatever you decide. | Judge options only on future costs and benefits; ask what you would choose if starting today. |
| Groupthink | A cohesive team converges quickly, dissent feels disloyal, and nobody voices the obvious objection. | Assign someone to argue the other side; collect views in writing before the meeting; invite an outside reviewer. |
| Resume-driven development | A technology is chosen because it is exciting to learn or looks good on a CV, not because it fits the problem. | Require every choice to be justified against the agreed criteria; budget learning time separately. |
| Hype and bandwagon | "Everyone is moving to X" stands in for analysis; conference talks from very large companies are applied to small teams. | Ask what problem X solved for its adopters and whether you have that problem at that scale. |
| Confirmation bias | Evidence for the favoured option is sought and remembered; evidence against it is explained away. | Write down in advance what result would change your mind, then run the spike or test. |
Worked example
Worked example: a weighted decision matrix
A food-delivery company is building a new order service. Orders involve payment and must never be lost or double-charged. The team of six knows PostgreSQL well and has no dedicated database administrator. Three options are on the table: (A) a managed PostgreSQL service from their cloud provider, (B) the provider's proprietary managed document database, and (C) PostgreSQL self-hosted on virtual machines. The team builds a weighted decision matrix: it agrees criteria and weights from the stakeholder concerns (5 = most important), then scores each option from 1 (poor) to 5 (excellent).
| Transactional integrity (weight 5) | A: 5, B: 3, C: 5. Multi-row transactions are central to orders and payments; the document store supports them with more restrictions. |
|---|---|
| Operational effort (weight 4) | A: 4, B: 5, C: 2. Self-hosting means patching, backups and failover by a team with no database specialist. |
| Team familiarity (weight 3) | A: 5, B: 2, C: 4. |
| Cost at expected load (weight 3) | A: 3, B: 4, C: 4. |
| Scaling headroom (weight 2) | A: 3, B: 5, C: 3. Expected growth is about three times in two years, well within a single large PostgreSQL instance. |
| Reversibility and lock-in (weight 2) | A: 4, B: 2, C: 5. Standard PostgreSQL can move between providers; the proprietary API cannot. |
| Weighted totals (maximum 95) | A: 25 + 16 + 15 + 9 + 6 + 8 = 79. B: 15 + 20 + 6 + 12 + 10 + 4 = 67. C: 25 + 8 + 12 + 12 + 6 + 10 = 73. |
| Sensitivity check | Raise scaling headroom to weight 5 (as if expecting fifty-fold growth): A 88, B 82, C 82. Lower operational effort to weight 1 (as if a platform team ran databases for them): A 67, B 52, C 67, a tie between A and C. |
| Decision | Option A, managed PostgreSQL. It wins under the agreed weights and stays first or joint first under plausible changes. Recorded consequences: a higher monthly bill than self-hosting; dependence on the provider's maintenance windows; a plan to keep schema and queries standard so that option C remains a fallback. |
The numbers do not make the decision; they make the reasoning visible. Anyone who disagrees can point to a specific weight or score instead of arguing about the whole.
The sensitivity check is the most informative step: it shows which assumptions the result depends on. Here the outcome hinges mainly on the team's lack of database operations capacity.
Matrices can be gamed by choosing criteria and weights after the favoured option is known. Agree criteria and weights before scoring, ideally with the stakeholders whose concerns they represent.
Recording decisions: a preview of ADRs
The second law says the why matters more than the how, so the why must be written down. The most widely used lightweight format is the Architecture Decision Record (ADR), proposed by Michael Nygard in a 2011 blog post. An ADR is a short text file, kept with the code in version control, that records one decision using the anatomy described above: title, status, context, decision and consequences. ADRs are never edited to change history; a later decision supersedes an earlier one and links to it, so the log tells the story of how the architecture evolved.
Chapter 4 covers templates, tooling and the habits that keep ADRs useful in Architecture Decision Records. The example below records the decision from the worked example.
ADR 7: Use managed PostgreSQL for the order service
Status: Accepted (2026-10-12)
Context
Orders and payments need multi-row transactions and must never be lost.
The team knows PostgreSQL well and has no database administrator.
Expected growth is about 3x in two years.
Decision
We will use the cloud provider's managed PostgreSQL service.
Consequences
+ Backups, patching and failover are handled by the provider.
+ Standard SQL keeps self-hosting or another provider open as a fallback.
- Monthly cost is about 30% higher than self-hosting at current load.
- Maintenance windows are set by the provider.
Revisit if write volume exceeds what one primary instance can handle.Check your understanding
What is the difference between Richards and Ford's first and second laws?
The first says every architectural choice is a trade-off. The second says the reasoning behind a choice (why) matters more than its implementation (how), because the why cannot be recovered from the code.
Give one example of a two-way door and one of a one-way door in a typical web application.
Two-way: the logging library used behind your own interface, or a cache's expiry setting. One-way: the data model of a system of record, or a public API that many partners already depend on.
Why can deciding too early be as harmful as deciding too late?
Too early means deciding with less information than you could have had, often by guessing. Too late means the decision is effectively made by default through assumptions already built into code or plans, or an option has expired.
What does a sensitivity check add to a weighted decision matrix?
It shows whether the winning option still wins when weights or scores change within plausible ranges, revealing which assumptions the decision depends on.
Sources and further reading
Have a question about this section? ArchitectBot, the course’s AI study assistant, answers from the course first.
Ask: “We are arguing about whether to adopt an event broker now or later. How do I tell whether this is a one-way door and when we actually need to decide?”