Module 1: What an Architect Really Does

BDUF versus the last responsible moment

Overview

This is the last of the four false images of the role, and it closes the module before the project. Big Design Up Front —BDUF— is the belief that a good architect designs the entire complete system before writing a line of code: every service, every contract, every decision, resolved in advance in an exhaustive document. It's the first cousin of the ivory tower (lesson 2), but with a different nuance: the ivory tower is about where the architect works (isolated, without going down to the site); BDUF is about when they decide (everything at the start, before having the information).

Against BDUF, this lesson installs the real architect's stance: decide each thing at the last responsible moment (LRM). The idea is precise and must be understood well because it's easy to deform in both directions. The last responsible moment is not "decide as late as possible" (that would be paralysis, which is also paid for); it's not "decide as early as possible" (that's BDUF, and you pay rework). It's deciding at the moment when you already have the information to decide well, but it isn't yet so late that the delay costs you. Each decision has its own last responsible moment, which arrives when its information matures. The real architect doesn't decide everything on day one nor postpone everything indefinitely: they decide each thing in its time. This lesson measures the overcost of not doing so —of deciding everything in advance, blind, and paying the rework—.

Connection with the module. It closes the false images and connects with lesson 4: if the architect's product is a reversible decision (lesson 4), BDUF is its enemy, because committing everything in advance is the most irreversible thing you can do. It's also the temporal flip side of lesson 6: the dictator centralizes in space (everything passes through them), BDUF centralizes in time (everything is decided at the start). Watch the frontier, which is especially important here: reversibility and the last responsible moment as a technique —how to compute that moment, how to structure a decision to defer it, the cost of not deciding thoroughly— is the sister guide architecture-decisions (its module 7). Here we work the mental stance of the craft: why the architect rejects BDUF and adopts the LRM as a way of thinking, not the mechanics of computing it.

An analogy: packing for a three-month trip

You're going on a three-month trip through several countries, with different climates, and you have to prepare your suitcase. There are three ways to approach the luggage, and only one is sensible.

BDUF: pack everything the first day, for the three months. You decide, before leaving, absolutely everything you'll use in ninety days: the clothes for each climate, the gift for the friend you'll see in month two, the medicines for a cold you might catch in month three. You pack a gigantic, extremely heavy suitcase, with decisions made today about situations you don't know yet. What happens in reality? Month two's "cold climate" turned out to be a heat wave, so the winter clothes were dead weight you carried for two months. You won't see month two's friend anymore because they changed plans, and the gift travels back and forth uselessly. The cold never came. You packed with day-one information for a trip that didn't exist yet, and you paid the price: carrying dead weight and, when reality changed, having to buy things anyway (rework) because what you packed was useless.

Paralysis: pack nothing, decide everything on the go. The other extreme: you leave with no suitcase, "I'll just buy what I need in each place". It sounds flexible, but you arrive at the first city at night, with no clean clothes, no charger, no basics, and you lose the first day sorting out what you could have brought. Deferring everything also costs.

The last responsible moment: pack what you already know, defer what you don't yet. You pack today what today's information already allows deciding well: the clothes for the first days (you know the climate), the basic and essential (charger, documents, medicines you do use). And you explicitly defer what depends on information you don't have yet: month two's clothes you'll buy there when you know the real climate; the gift you choose when you confirm you'll see the friend. You don't carry dead weight (not BDUF) nor leave naked (not paralysis): you decide each thing when its information matures. Your suitcase is light and your decisions right, because each one was made with the data available at its moment.

The point: BDUF packs the three months on day one and carries dead weight plus rework; the last responsible moment packs each thing when it knows. The real architect is the sensible traveler. They don't design all of Mercado in advance —which payments provider, how the catalog splits off, what protocol between orders and shipping— because many of those decisions depend on information only construction and operation will give. They decide today what they already know today (the technological base, which as we saw in lesson 2 survives), and defer the rest to its last responsible moment. This lesson measures the dead weight and rework of whoever packs everything on day one.

Worked example: the overcost of deciding blind

We model six of Mercado's design decisions. Each has a week in which its information matures (info_ready_week): the moment when there's finally data to decide it well —the real load, how the squads organized, how a provider behaved—. We compare two stances:

  • BDUF decides the six in week 0, before that information. The ones it decides ahead of time turn out wrong and have to be redone (rework).
  • LRM (last responsible moment) decides each one in its week of mature information. No rework, because each decision was made with the available data.
# BDUF (Big Design Up Front) vs deciding at the LAST RESPONSIBLE MOMENT (LRM).
# Each Mercado decision has a week in which there's finally information
# to decide it well (info_ready_week). BDUF decides EVERYTHING in week 0, before
# that info: the ones it decides ahead of time turn out wrong and must be redone
# (rework). LRM decides each one in its info week: no rework.
DECISIONS = [
    # (id, info_ready_week, rework_cost_if_decided_blind)
    ("payments_provider_count",  6, 20000),
    ("catalog_service_boundary", 9, 35000),
    ("orders_shipping_protocol", 4, 18000),
    ("search_index_strategy",    8, 15000),
    ("cache_layer_shape",        5, 12000),
    ("edge_load_balancer",       0,     0),   # this one IS known from day 0
]

DECIDE_COST = 3000    # deciding one (analysis + record), same in both stances

bduf_cost = 0
lrm_cost = 0
for did, ready, rework in DECISIONS:
    # BDUF: decides everything on day 0. If the info wasn't ready (ready>0), it
    # decides blind and then redoes -> pays deciding + rework.
    bduf_cost += DECIDE_COST + (rework if ready > 0 else 0)
    # LRM: decides each one when its info matures -> pays only deciding, no rework.
    lrm_cost += DECIDE_COST

print(f"{'decision':<26}{'info_ready':>12}{'BDUF outcome':>16}")
print("-" * 54)
for did, ready, rework in DECISIONS:
    outcome = "blind -> rework" if ready > 0 else "ok (day 0)"
    print(f"{did:<26}{('week ' + str(ready)):>12}{outcome:>16}")

print()
print(f"Total BDUF cost (decide everything day 0): {bduf_cost:>7,.0f} USD")
print(f"Total LRM  cost (decide when it matures):  {lrm_cost:>7,.0f} USD")
print(f"BDUF overcost from deciding blind:         {bduf_cost - lrm_cost:>7,.0f} USD")
print()
print("BDUF doesn't fail for planning; it fails for deciding EVERYTHING before")
print("having the info and paying the rework. The real architect decides at the")
print("last responsible moment: neither before (BDUF) nor after (the sister guide's paralysis).")

What to expect. Running the file, the output is exactly this:

decision                    info_ready    BDUF outcome
------------------------------------------------------
payments_provider_count         week 6 blind -> rework
catalog_service_boundary        week 9 blind -> rework
orders_shipping_protocol        week 4 blind -> rework
search_index_strategy           week 8 blind -> rework
cache_layer_shape               week 5 blind -> rework
edge_load_balancer              week 0      ok (day 0)

Total BDUF cost (decide everything day 0): 118,000 USD
Total LRM  cost (decide when it matures):   18,000 USD
BDUF overcost from deciding blind:         100,000 USD

BDUF doesn't fail for planning; it fails for deciding EVERYTHING before
having the info and paying the rework. The real architect decides at the
last responsible moment: neither before (BDUF) nor after (the sister guide's paralysis).

Read the right-hand column, because it separates the single decision BDUF got right from the five it blew up.

Notice edge_load_balancer: its info_ready_week is 0, and its outcome is ok (day 0). It's the only one BDUF decides well, and not by luck: it's a decision whose information already existed on day one —putting an HTTP load balancer at the edge is a solid bet that doesn't depend on knowing the future load or how the squads will organize—. It's exactly the kind of decision that survived contact with reality in lesson 2. For these, deciding on day one is fine, because their last responsible moment is day one.

The other five are BDUF's story. payments_provider_count can't be decided well until week 6, when there's data on the providers' real behavior; BDUF decided it in week 0, blind, and when the information arrived, the decision turned out wrong and had to be redone —20000 dollars of rework—. catalog_service_boundary matures in week 9 (you need to see how the squads and the data really organize before drawing the service boundary); deciding it on day one cost 35000 in rework. And so the five: each decided before its information existed, each redone afterward.

The final number is the argument: BDUF costs 118000 dollars; LRM, 18000; the overcost from deciding blind is 100000. Notice exactly where that overcost comes from: not from the analysis or the record —those cost the same in both stances (3000 per decision, 18000 in total)—. It comes entirely from rework: the five decisions BDUF made ahead of time and had to redo. BDUF isn't more expensive for planning more; it's more expensive for deciding before having something to decide with, and paying the correction afterward. I repeat the nuance because it's the heart of the lesson and the easiest to deform: BDUF's problem isn't thinking in advance —thinking, exploring, sketching is good—; the problem is committing in advance, freezing decisions whose information hasn't matured yet.

And here's the symmetry that completes the stance. Deciding before the last responsible moment is BDUF: you pay rework (this lesson's 100000). Deciding after the last responsible moment is paralysis: you pay the cost of the default and the delay (which the sister guide measures in depth). The real architect navigates between the two: neither before nor after; each decision in its time, when its information matures but before the delay costs. The last responsible moment is that equilibrium point, a different one for each decision.

As bars, the overcost jumps out:

Total cost: BDUF vs. last responsible moment (USD)
 BDUF (all day 0)  |###############################  118,000
 LRM  (each thing in its time) |####                  18,000
                    ────────────────────────────────
 BDUF overcost = 100,000, ALL rework from deciding blind.

Deep dive: why BDUF is so tempting (and how to recognize the last responsible moment)

BDUF, like the ivory tower, has an appeal that must be understood to resist it, and the last responsible moment has a practical difficulty that must be resolved.

Why BDUF tempts. First, it gives a feeling of control: having everything decided in advance feels like having the project mastered, while leaving decisions open feels like going blind. The irony is it's the reverse —deciding blind on day one is what goes blind; deferring until you have the data is the informed one—. Second, it responds to a real organizational pressure: stakeholders ask for "the complete plan" before approving budget, and a document that says "we'll decide this in week 6 when we have the data" feels less solid than one that decides it all now. Third, there's an underlying confusion between planning and deciding: they're different things, and BDUF fuses them. You can —and should— plan in advance (sketch the direction, identify the decisions to come, anticipate the risks) without committing each decision in advance. The plan can say "here we'll have to choose the protocol between orders and shipping, and we'll decide it when we see the load"; that's planning without falling into BDUF.

How to recognize a decision's last responsible moment. The LRM stance is easy to state and hard to apply without a practical guide. The question that operationalizes it is twofold:

  1. What information am I missing to decide this well, and when will I have it? If the decision is missing a concrete piece of data that will arrive at an identifiable moment (the next peak's load, how the provider behaves after a month, how the squads organized), its last responsible moment isn't today: it's when that data matures. Deciding earlier is BDUF.

  2. When does not having decided start to cost me? The last responsible moment isn't "forever after": it arrives when the delay starts to cost —when other decisions block waiting for this one, when the default entrenches, when the team can't move forward without knowing—. Deferring beyond that point is paralysis.

The last responsible moment is the window between those two: after the information matures, before the delay costs. If that window exists, you defer until you enter it. If the data is already there (like edge_load_balancer), you decide now. If the delay already costs and the data isn't arriving, you decide with what you have and make the decision reversible (lesson 4) to correct when the data appears. Notice how well the module's pieces fit: reversibility (lesson 4) is what makes it safe to defer, because if you're forced to decide before the last responsible moment, a reversible decision is corrected cheaply when the information arrives.

A warning about the other extreme. Just as this module doesn't say "don't plan", it also doesn't say "defer everything". An architect who uses "last responsible moment" as an excuse to never decide fell into paralysis, which is as expensive as BDUF from the other side. The LRM discipline has both halves: deferring what hasn't matured yet and committing as soon as it matures or as soon as the delay starts to cost. The mature architect isn't the one who decides earliest (BDUF) nor the one who decides latest (paralysis); it's the one who decides each thing in its time, and knows how to recognize when that time is for each decision. (The formal calculation of that point —the value of the information, the cost of deferring week by week— is the sister guide; here the stance of seeking it is enough.)

Common mistakes

Confusing planning with deciding (and committing everything in advance). What happens: the architect produces an exhaustive design document that not only sketches the direction but freezes every decision —protocol, providers, service boundaries— before writing code, and then the team executes decisions made blind that reality keeps invalidating. Why it happens: "having a plan" is fused with "having decided everything", when planning (sketching, anticipating) and deciding (committing) are different things. How to spot it: if the starting document decides with certainty things that depend on information that doesn't exist yet (the real load, how the squads will organize), it's BDUF disguised as a plan. How to fix it: separate the two layers —the plan identifies what will have to be decided and when its information will mature; the decisions are each made in their time—. A good plan can say "here goes a pending decision, with this trigger"; that's planning without committing. The overcost of committing blind was 100000 in the example, all rework.

Using "last responsible moment" as an excuse to never decide (paralysis). What happens: the architect defers decisions indefinitely "because it's not the last responsible moment yet", when in reality the information has already matured or the delay is already costing. Why it happens: deferring feels safe (you're not wrong if you don't decide), and "LRM" gives a professional-sounding justification for not committing. How to spot it: if on asking "what specific information are you waiting for and when will it arrive?" there's no concrete answer, you're not at the last responsible moment; you're in paralysis. How to fix it: apply the two halves of the discipline —defer only while an identifiable piece of data with a date is missing, and commit as soon as that data arrives or the delay starts to cost—. The last responsible moment is a decision point, not a perpetual postponement. (The cost of not deciding, measured week by week, is the sister guide.)

Applying the same moment to all decisions. What happens: the architect treats all decisions with the same chronology —either all on day one (BDUF), or all "later"— without noticing that each has its own last responsible moment. Why it happens: it's simpler to have a single policy ("let's decide everything now" or "let's decide everything later") than to evaluate decision by decision when its information matures. How to spot it: if the architect decided edge_load_balancer (known on day one) and catalog_service_boundary (which matures in week 9) at the same moment, they ignored that they have different clocks. How to fix it: recognize that the last responsible moment is per decision: the technological-base ones whose evidence already exists are decided early; the ones that depend on load, operation, or organization are deferred until that data matures. Lesson 2 itself anticipated it: three of the diagram's decisions survived (their info existed on day one) and seven were redone (their info lived in construction). Each decision, its clock.

Exercises

Exercise 1 — Decide now or defer? For each of these Mercado decisions, say whether its last responsible moment is probably "day one" or "later", and what information you'd have to wait for in the second case: (a) choosing the base language and framework of the services; (b) deciding whether search will have its own index or query the catalog database; (c) choosing the log format for cross-cutting observability; (d) deciding the number of payment providers.

See solution
  • (a) Language and base framework → day one. Its information already exists: the team knows its skills, the hiring market, the ecosystem. It doesn't depend on the future load or on how Mercado evolves. It's a base decision, like edge_load_balancer: deciding it early is fine, and deferring it would only block everything else. Besides, it's expensive to reverse, so it's worth deciding carefully but soon.
  • (b) Search's own index vs. catalog database → later. It depends on the real search volume and the catalog size, data that doesn't exist on day one. Its last responsible moment arrives when there's real traffic showing whether the catalog database holds up or not. Deciding it on day one is guessing (BDUF); waiting for the load data is LRM.
  • (c) Log format → day one (with a nuance). The format (structured JSON with certain fields) can and should be fixed early as a guardrail, because cross-cutting observability needs it from the start and its info doesn't depend on the future. It's a broad-convention decision, like the ones that survived in lesson 2.
  • (d) Number of payment providers → later. It depends on the single provider's real availability (does it go down?), the volume (does it justify redundancy?), and the cost. That information matures with operation, not on day one. It's exactly the example's payments_provider_count, with a last responsible moment in week 6.

The pattern: base and convention decisions whose evidence already exists are decided early; the ones that depend on load, operation, or organization are deferred until their data matures. Each decision, its clock.

Exercise 2 — The plan the VP asks for. The VP demands "Mercado's complete design before approving the budget: I want all decisions made". Knowing that deciding them all now would cost 100000 in rework, how do you give them a plan that satisfies them without falling into BDUF?

See solution

The key is to separate what the VP really needs (confidence that there's a direction and risk management) from what they literally ask (all decisions frozen). You give them a plan that plans without committing blind:

  • The direction and high-level architecture, firm. The decisions whose information already exists —language, technological base, the guardrails, the load balancer— you do decide and present as firm. That gives the VP the solidity they seek.
  • The pending decisions, explicit and with a trigger. Instead of hiding that there are open decisions, you make them visible as part of the plan: "these five decisions —payment providers, catalog boundary, orders/shipping protocol, search index, cache shape— depend on information we'll have in weeks 4 to 9; we'll decide them there, with the data, instead of guessing today". Each one with its trigger (what data unblocks it).
  • The business argument. You explain that deciding those five now doesn't give more control, it gives more rework: 100000 dollars of decisions to redo when reality contradicts them. Deferring them to the last responsible moment isn't "not having a plan"; it's the plan that avoids that cost. A VP understands well the idea of not committing capital ahead of time —it's their own craft—.

That way the VP gets a plan that's firm where it can be and honest where it can't, with explicit risk management. That's more solid, not less, than a BDUF that freezes decisions blind. (How to present it with the right level of diagram for them is module 3; the argument of the cost of deferring vs. deciding is the sister guide.)

Exercise 3 — BDUF and paralysis, the two errors. A colleague says: "so the lesson is clear: never decide in advance, defer everything as much as possible". Correct their conclusion by showing how it falls into the opposite error, and state the correct stance precisely.

See solution

Their conclusion inverts BDUF but falls into the other extreme: paralysis. "Never decide in advance, defer everything as much as possible" treats deferring as a good in itself, when deferring also costs —the cost of the default, of the decisions blocked waiting, of the delay—. If you defer a decision whose information has already matured (like edge_load_balancer, known on day one), you're not being prudent; you're delaying for no reason and blocking what depends on it. And if you defer a decision beyond the point where its delay starts to cost, you pay the paralysis the sister guide measures.

The correct stance isn't "decide early" (BDUF) or "defer everything" (paralysis), but the last responsible moment, per decision: decide each thing when its information matures but before the delay costs. Precisely, there are three cases:

  • If the information already exists (technological base, conventions): decide now; deferring only blocks.
  • If the information will mature at an identifiable moment: defer until then, and decide when it arrives.
  • If the delay is already costing and the information isn't arriving: decide with what you have and make it reversible (lesson 4) to correct when the data appears.

The discipline has both halves: deferring what hasn't matured yet and committing as soon as it matures or the delay costs. The mature architect decides each thing in its time, neither before nor after —and recognizes that this "time" is different for each decision—.

Summary and next step

In this lesson you took apart the last false image of the role: Big Design Up Front, designing and committing everything in advance before having the information. You saw, with the three-month trip's suitcase, that packing the three months on day one carries dead weight and forces rework, while packing each thing when you know keeps the suitcase light and the decisions right. And you measured it: BDUF costs 118000 dollars against 18000 for the last responsible moment, an overcost of 100000 that is all rework —not for planning, but for deciding blind before the information matured—. The real architect's stance is the last responsible moment: each decision in its time, neither before (BDUF, you pay rework) nor after (paralysis, you pay the default), with reversibility as the net for the ones the delay forces to decide early.

Before moving on you should be able to: distinguish planning (good, anticipating the direction) from committing in advance (BDUF); state the last responsible moment with its two halves (after the info matures, before the delay costs); recognize that each decision has its own clock; and see how lesson 4's reversibility makes deferring safe.

Lesson 8 is the project that integrates the whole module. You'll take the role of Mercado's current architect, diagnose which of the four false images they suffer —ivory tower, detached from the code, dictator/bottleneck, BDUF—, measure the coordination cost of their way of working, and produce a role charter that splits what the architect owns, what they delegate, and how they enable. Executed, with the wait cost before and after. It's the whole module put to work on a case.

Resources

  • Mary and Tom Poppendieck, Lean Software Development (Addison-Wesley, 2003) — the source of the "last responsible moment" concept: defer the commitment until the last moment when the decision can be made with sufficient information, without the delay costing. This lesson's central stance. In English.
  • Martin Fowler, "Is Design Dead?" — martinfowler.com/articles/designDead.html. On why evolutionary design beats complete up-front design, and how design is a continuous activity, not an initial document. In English.
  • Barry Boehm, "Get Ready for Agile Methods, with Care" (IEEE Computer, 2002) — the classic analysis of the balance between planning in advance and deciding late, and why the optimal point depends on the cost of change. In English.
  • Mark Richards and Neal Ford, Fundamentals of Software Architecture, 2nd ed. (O'Reilly, 2020), on evolutionary architecture and why the architect designs for change, not for permanence. Reversibility and the LRM as a technique in depth are the sister guide architecture-decisions (module 7); the mental stance is this lesson. In English.