Module 6: Designing for Change
Designing the seams
Overview
The two previous lessons left the architect between two abysses. On one side, over-engineering (lesson 5): over-preparing, building flexibility for every imaginable future, paving twelve lanes for a town. On the other, under-engineering (lesson 6): under-preparing, refusing to leave a single seam, setting everything in concrete and painting yourself into a corner. This lesson —the heart of the module— shows the path between the two: designing the seams at the sensible point. It's not qualitative advice ("find the balance"); it's a decision that's calculated, because lessons 3, 5, and 6 already gave you all the pieces of the calculation.
The idea that orders everything is a phrase to burn in: designing for change is not designing for EVERY imaginable change. The architect who confuses the two falls into over-engineering, because imaginable changes are infinite and preparing them all is impossible and ruinous. Designing for change, well understood, is building the seam only where the change is probable enough to pay for itself, and deferring everything else. The deciding variable isn't fear (which pushes toward over-engineering), nor laziness (which pushes toward under-engineering), but the probability of the change, compared against its break-even point. This lesson executes that right-sizing on a portfolio of Mercado futures, and shows that it beats both extremes at once —not by a little, by a lot—.
Connection with the module. It's the synthesis of the three previous lessons (this one closes the arc: optionality → over → under → the middle). It gathers the break-even point of lesson 3 (is the seam worth it?), the over-engineering mistake of lesson 5 (don't build for the improbable) and the under-engineering one of lesson 6 (do build for the probable) into a single executable procedure. After this lesson, the project (lesson 8) has you apply it from scratch on a new case. Frontier with the sister guide: here we don't formally classify each decision or write the ADR; we work the stance and criterion of the architect who right-sizes the evolution —the mechanics of recording and classifying those decisions is architecture-decisions—.
An analogy: the urban planner who reserves the right of way —and only the one that's needed
Come back one last time to the urban planner, because the module's three merge here into a single one who does their job well.
Remember the three. The first planner (under-engineering) built every meter up to the edge, leaving no space; when the city grew, there was no way to open the avenue and demolition was needed. The second (over-engineering) paved twelve lanes and an airport for three thousand inhabitants; it drained the budget on empty infrastructure. The third —the good one— did neither: they reserved the right of way, the strip of land where, if the traffic arrives, the avenue will be opened cheaply.
But now look more closely at what the third planner does, because their true mastery isn't "reserving land" in the abstract —it's choosing where—. Facing the plan of the future city, they don't reserve the right of way everywhere (that would be the second planner, freezing half the city "just in case"). Nor nowhere (the first). They reserve the strip where growth is probable: the avenue toward the area already being populated, the corridor toward the road connecting to the big city, the space for the water line the obvious expansion will need. And they do not reserve for the improbable: they leave no land for a seaport (the town is inland), nor for a second airport runway that won't come. Their plan is a map of probabilities: reserve where it's probable, build what's needed today, and leave the rest free for the city to use now.
That's the module's synthesis, and it's Mercado's architect's. They don't leave seams everywhere (over-engineering) nor nowhere (under-engineering); they leave the seam where the change is probable: the interface to extract the catalog (probable, the business is growing), the abstraction of the payment provider (probable, finance is negotiating it), the boundary between reviews and recommendations (probable, they're distinct domains). And they do not leave a seam where the change is improbable: they don't abstract to turn Mercado into a social network, don't prepare 40 languages for one country, don't build the plugin marketplace no one asked for. The right of way is reserved for the probable avenue; the rest of the land is left free. This lesson turns that "where it's probable" into a calculation, and measures how much it beats both extremes.
Worked example: right-sizing against the two extremes
We're going to execute the synthesis. We take a portfolio of possible futures of Mercado, mixing —on purpose— high-probability changes (the ones lesson 6 would say "prepare") with low-probability changes (the ones lesson 5 would say "don't prepare"). Each future has its probability (p), the cost of leaving the seam today (seam), the cost of adapting through it if you left it (adapt), and the cost of rewriting if you didn't leave it (rewrite).
We compare three stances —the two abysses and the middle—:
rigid— under-engineering: builds no seam. For each future it pays the expected cost of rewriting,p × rewrite.over_engineered— over-engineering: builds all the seams. For each future it paysseam + p × adapt, whether justified or not.right_sized— the sensible point: builds the seam only where it pays for itself —where the cost of building it (seam + p × adapt) is less than the cost of not building it (p × rewrite)— and defers the rest. For each future it chooses the cheaper of the two, future by future.
The right_sized decision, future by future, is exactly the break-even comparison of lesson 3: build the seam if it comes out cheaper than risking the rewrite; defer (YAGNI) if not:
# Designing the seams: neither over-engineering (a seam for everything) nor under-engineering
# (a seam for nothing). The sensible point: build the seam ONLY where the change
# is probable enough for the seam to pay for itself; defer the rest (YAGNI).
# Each possible Mercado future:
# p : probability that the change arrives
# seam : cost of building the seam today
# adapt : cost of adapting LATER if there's a seam
# rewrite : cost of rewriting if there's NO seam
PORTFOLIO = [
# (name, p, seam, adapt, rewrite)
("monolith_to_services", 0.90, 8000, 10000, 90000),
("second_payments_provider", 0.70, 4000, 5000, 40000),
("reviews_and_ratings", 0.50, 6000, 6000, 30000),
("international_currencies", 0.25, 9000, 8000, 26000),
("plugin_marketplace", 0.05, 20000, 15000, 40000),
("white_label_multitenant", 0.03, 25000, 12000, 35000),
]
def cost_build(p, seam, adapt, rewrite):
return seam + p * adapt # seam today + expected adaptation
def cost_defer(p, seam, adapt, rewrite):
return p * rewrite # no seam: expected rework if it arrives
rigid_total = over_total = right_total = 0
built, deferred = [], []
print(f"{'future':<28}{'p':>6}{'build':>10}{'defer':>10} right-sized decision")
print("-" * 74)
for name, p, seam, adapt, rewrite in PORTFOLIO:
b = cost_build(p, seam, adapt, rewrite)
d = cost_defer(p, seam, adapt, rewrite)
rigid_total += d # rigid never builds a seam
over_total += b # over-engineered always builds
if b <= d:
right_total += b
decision = "BUILD seam"
built.append(name)
else:
right_total += d
decision = "defer (YAGNI)"
deferred.append(name)
print(f"{name:<28}{p:>6.2f}{b:>10,.0f}{d:>10,.0f} {decision}")
print("-" * 74)
print(f"{'rigid (0 seams, under-engineered)':<44}{rigid_total:>10,.0f}")
print(f"{'over_engineered (seam for EVERYTHING)':<44}{over_total:>10,.0f}")
print(f"{'right_sized (seam where it pays for itself)':<44}{right_total:>10,.0f}")
print()
print(f"Builds seam in: {', '.join(built)}.")
print(f"Defers (YAGNI): {', '.join(deferred)}.")
print("The sensible point beats both extremes: the deciding variable is the")
print("PROBABILITY of the change, not fear nor laziness.")
What to expect. Running the file, the output is exactly this:
future p build defer right-sized decision
--------------------------------------------------------------------------
monolith_to_services 0.90 17,000 81,000 BUILD seam
second_payments_provider 0.70 7,500 28,000 BUILD seam
reviews_and_ratings 0.50 9,000 15,000 BUILD seam
international_currencies 0.25 11,000 6,500 defer (YAGNI)
plugin_marketplace 0.05 20,750 2,000 defer (YAGNI)
white_label_multitenant 0.03 25,360 1,050 defer (YAGNI)
--------------------------------------------------------------------------
rigid (0 seams, under-engineered) 133,550
over_engineered (seam for EVERYTHING) 90,610
right_sized (seam where it pays for itself) 43,050
Builds seam in: monolith_to_services, second_payments_provider, reviews_and_ratings.
Defers (YAGNI): international_currencies, plugin_marketplace, white_label_multitenant.
The sensible point beats both extremes: the deciding variable is the
PROBABILITY of the change, not fear nor laziness.
Read the three totals first, and then the table that explains them, because here the whole module closes.
The three totals: rigid 133550, over-engineered 90610, right-sized 43050. The sensible point beats both extremes, and not by a little: it costs half of over-engineering and less than a third of the rigid one. This is what matters about the lesson: it's not that right-sizing is "a good compromise" that sacrifices something from each side; it's that it dominates both. Neither over-preparing nor under-preparing comes close to preparing just enough. The reason is simple once you see it: the two extremes apply a single rule to all futures (rigid: never prepare; over: always prepare), and a single rule is wrong for some futures by definition. Right-sizing decides future by future, so it never makes the mistake of applying the wrong rule.
Now the table, which shows how it decides, and is where the module's criterion lives. Look at the two columns build and defer for each future, and what right-sizing decides:
monolith_to_services(p=0.90): building the seam costs 17000, rewriting costs 81000 expected. Building wins by a landslide → build. It's the case of lesson 6: probable change, leave the seam.second_payments_provider(p=0.70) andreviews_and_ratings(p=0.50): building (7500 and 9000) is cheaper than expected rewriting (28000 and 15000) → build. Probable changes, seam.international_currencies(p=0.25): here the line is crossed. Building the seam costs 11000; the expected rework is only 6500. Building would be more expensive than risking the rewrite → defer. The probability (25%) no longer justifies the seam for thisseam/rewrite.plugin_marketplace(p=0.05) andwhite_label_multitenant(p=0.03): building costs 20750 and 25360; the expected rework is barely 2000 and 1050 → defer clearly. They're the imagined futures of lesson 5: tiny probability, don't prepare.
Notice the pattern: right-sizing builds the three top seams (high probability) and defers the three bottom ones (low probability). There's no fixed "yes" or "no" rule; there's a cutoff line that each future's probability crosses or doesn't cross, given its seam cost and rewrite cost. That's exactly the break-even point of lesson 3 applied future by future. The code's phrase sums it up: the deciding variable is the probability of the change, not fear nor laziness. The architect who decides by fear builds everything (over); the one who decides by laziness builds nothing (rigid); the one who decides by probability builds just enough (right-sized).
As bars, the dominance of the sensible point:
Total expected cost (USD): the two extremes vs the sensible point
rigid (under-eng) |#################################### 133,550
over_engineered |######################## 90,610
right_sized |########### 43,050
────────────────────────────────────
The middle isn't a "compromise": it DOMINATES both extremes.
Deep dive: designing for change is not designing for every change
It's worth pausing on the phrase that orders the lesson, because it's the one that separates the architect who understood the module from the one who misunderstood it: designing for change is not designing for every imaginable change.
The misunderstanding is easy and common. An architect reads "you have to design for change" (the module's thesis) and concludes "then my system must be prepared for any change I can think of". That conclusion is direct over-engineering: since imaginable changes are infinite —Mercado could become a social network, a bank, a streaming platform, whatever—, preparing them all is impossible, and the attempt produces a system drowned in unused flexibility. "Designing for change" can't mean "preparing for everything", because "everything" doesn't fit. It has to mean something else, more modest and more useful: preparing for the probable change, and only for it. Right-sizing is the discipline of translating "design for change" into "design for the few changes the evidence says will probably come", not into "design for the infinite catalog of what could happen".
Where the probabilities come from —and why this isn't guesswork—. A skeptic will say: "but no one knows the exact probability of these futures; you're making up numbers". It's a fair objection, and the answer is the same as in lesson 3: right-sizing doesn't need exact probabilities, it only needs to place them relative to the cutoff line, and for that there's real evidence, not guesswork. monolith_to_services has high probability because the business is already growing and the squads already feel the monolith's pain —it's a signal, not a hunch—. second_payments_provider is probable because finance is already negotiating. plugin_marketplace is improbable because no one has asked and there's no platform strategy. The architect doesn't guess; they read the business's signals —the roadmap, the conversations with stakeholders (module 5), the pain the squads already report (module 2)— and place each future as clearly probable, clearly improbable, or doubtful. Only the doubtful ones require fine judgment, and there the asymmetry of lesson 6 helps resolve. Right-sizing turns the business knowledge the architect already has into seam decisions; it doesn't invent probabilities, it derives them from what the business is signaling.
The seam isn't the service: prepare cheaply, don't build expensively. A point lessons 5 and 6 touched and that here is worth consolidating, because it's where many architects get confused. When right-sizing says "build the seam for monolith_to_services", it does not say "build the microservices now". It says: leave the seam —the clear interface, the separate tables, the contract— that will make the future extraction cheap. The seam is the right of way (cheap, today), not the paved avenue (expensive, when it's needed). Confusing the two reintroduces over-engineering through the back door: "right-sizing said prepare the monolith-to-services, so I built the services" is exactly paving the twelve lanes. The correct seam for monolith_to_services costs 8000 (a design decision, not a distributed system); building the services would cost hundreds of thousands and would be premature. Right-sizing decides where to reserve the right of way, not where to build the avenue. The avenue is built when the traffic arrives, not before.
Right-sizing is a snapshot that's revised, not a sentence. A final consequence that connects with lesson 2 and closes the module's circle. The example's portfolio has today's probabilities, and those probabilities change: an improbable future can become probable when the business moves (if Mercado announces international expansion, international_currencies jumps from 0.25 to 0.90 and crosses the cutoff line). That's why right-sizing isn't a decision made once and frozen —that would be treating the architecture as final, the mistake of lesson 2—. It's a periodic review: every so often, the architect returns to the portfolio, updates the probabilities with the new business signals, and reevaluates which seams are worth building now that were deferred before. Designing the seams is itself a flow of decisions, not an artifact. The architect who right-sizes once and never revises paints themselves into a different corner: that of an evolution plan that became obsolete. The module's complete stance is circular: the architecture is a flow (L2), so the seams are decided with optionality (L3), avoiding the two abysses (L5, L6), in a right-sizing (L7) that is also a flow that's revised. No decision is final —not even the decision of which seams to leave—.
Common mistakes
Confusing "designing for change" with "designing for every change". What happens: the architect takes the module's thesis ("design for change") and takes it to "my system must be ready for any imaginable change", and falls straight into over-engineering. Why it happens: "designing for change" sounds like "preparing", and "preparing" slides easily to "preparing for everything". How to spot it: if the system has seams and abstractions for futures no one has signaled, or if the justification for a preparation is "anything could happen", change was confused with every change. How to fix it: remember that designing for change is designing for the probable change —the few the business evidence signals—, not for the infinite catalog of the imaginable. Right-sizing builds three seams of six, not all six.
Building the avenue instead of reserving the right of way. What happens: right-sizing says "prepare for this probable change" and the architect builds the complete solution in advance —the microservices, the entire multi-currency system— instead of just the cheap seam that will make the future construction easy. Why it happens: "preparing" is interpreted as "building the thing", not as "leaving the space to build it". How to spot it: if preparing a probable change cost tens or hundreds of thousands (not thousands), you probably built the avenue, not the right of way. How to fix it: distinguish the seam (interface, contract, boundary —cheap, today) from the solution (the service, the system —expensive, when the change arrives); right-sizing decides where to leave the seam, not where to build the solution. In the example, the monolith's seam costs 8000, not the hundreds of thousands of the services.
Right-sizing once and freezing the plan. What happens: the architect does the portfolio analysis, decides which seams to build, and treats that decision as definitive —doesn't revise when the probabilities change—. A future deferred as improbable becomes probable, and no one reevaluates until the change arrives with no seam. Why it happens: doing the analysis feels like closing the topic, and revising it periodically takes discipline. How to spot it: if the futures portfolio was assembled a year ago and no one has looked at it again despite the business changing, the plan is frozen. How to fix it: treat right-sizing as a flow, not a sentence —revise it periodically, update the probabilities with the new business signals, and reevaluate which seams are worth building now—. It's lesson 2 applied to the seam decision: not even the evolution plan is final.
Exercises
Exercise 1 — Move a probability. In the example, international_currencies (p=0.25) is deferred: building the seam costs 11000 and the expected rework is only 6500. Now marketing officially announces the expansion to three countries next year, and the probability rises to 0.90. Without running code, recalculate the two options (build and defer) with the new probability and say what right-sizing decides now. What does this teach about why right-sizing must be revised?
See solution
With international_currencies at p = 0.90 (the other numbers the same: seam = 9000, adapt = 8000, rewrite = 26000):
- build =
seam + p × adapt=9000 + 0.90 × 8000=9000 + 7200= 16200. - defer =
p × rewrite=0.90 × 26000= 23400.
Now build (16200) is cheaper than defer (23400), so right-sizing builds the seam —when before, at p = 0.25, it deferred it—. The decision reversed without a single cost number changing (seam, adapt, rewrite are the same); the only thing that changed was the probability, and that was enough to cross the cutoff line.
What it teaches: right-sizing isn't a sentence, it's a snapshot that depends on the probabilities of the moment, and the probabilities change when the business moves. A future rightly deferred today (improbable) can become probable tomorrow (a marketing announcement, a new signal), and then the seam that wasn't worth it before now is. If the architect had right-sized once and frozen the plan, they'd keep deferring the multi-currency seam even after the expansion announcement —and the expansion would arrive to find no seam, with the checkout hardcoded to one country, paying the rewrite of lesson 6—. That's why right-sizing must be revised periodically: it's itself a flow of decisions (lesson 2), not an artifact that's frozen. Not even the plan of which seams to leave is final.
Exercise 2 — Why it dominates, not compromises. The text insists that right-sizing dominates the two extremes (43050 against 90610 and 133550), not that it's "a good compromise between them". Explain why a naive compromise —for example, "let's build half the seams at random"— wouldn't achieve this, and what exactly right-sizing does that no extreme and no blind middle point can do.
See solution
A naive compromise —"let's build half the seams", chosen with no criterion— wouldn't dominate the extremes because it would still apply a rule blind to probability. If you choose half at random, you could build the seam for plugin_marketplace (p=0.05, where build=20750 against defer=2000: an enormous waste) and defer the one for monolith_to_services (p=0.90, where defer=81000 against build=17000: a catastrophe). A blind middle point makes both mistakes at once —over-engineering in the improbable futures it prepared, under-engineering in the probable ones it deferred— and can turn out as bad or worse than any extreme.
What right-sizing does, and no extreme or blind middle point can do, is decide each future by its own probability, comparing its cost of building against its cost of deferring (the break-even point of lesson 3, future by future). For each future it chooses the cheaper of the two, so —by construction— it's never worse than the best of the two extremes in that future, and almost always strictly better. The extremes fail because they apply a single rule to all futures: rigid gets the improbable ones right (correctly defers) but sinks on the probable ones (wrongly defers the cheap seams); over_engineered gets the probable ones right (correctly builds) but wastes on the improbable ones (wrongly builds very expensive seams for nothing). Right-sizing takes the good of each extreme future by future: it defers where rigid would be right and builds where over_engineered would be right. That's why it's not a compromise that sacrifices something from each side; it's the optimal policy that dominates both, because each individual decision is the best possible. The module's "middle" isn't averaging the extremes; it's choosing well case by case.
Exercise 3 — The seam isn't the solution. A Mercado architect, after the analysis, announces: "right-sizing says to prepare monolith_to_services and second_payments_provider, so I'm going to build the catalog microservices and integrate the two payment providers this quarter". Explain what they misunderstood, how much more their interpretation would cost versus the correct one, and what they should actually build.
See solution
They misunderstood the difference between the seam and the solution —between reserving the right of way and paving the avenue—. Right-sizing said "build the seam" for those two futures, not "build the complete solution". The monolith_to_services seam is a clear interface and separate tables inside the monolith (costs 8000 in the model, a design decision); building the catalog microservices is a whole distributed system (networks, deployments, consistency), which costs orders of magnitude more and which the business hasn't asked for yet. Same with payments: the seam is an abstraction over the provider (costs 4000); integrating the two providers for real is the expensive work done when the second provider arrives, not before.
How much more it would cost: instead of the two cheap seams (8000 + 4000 = 12000), they'd be building the two complete solutions in advance —easily hundreds of thousands between the microservices and the double payment integration—, and on top of that prematurely, for changes that haven't arrived. That is, they transformed right-sizing (which was saving them money) into direct over-engineering (paving the twelve lanes): building the avenue today instead of reserving the right of way. It's exactly the "building the avenue instead of reserving the right of way" mistake, sneaking over-engineering in through the back door with the excuse that "the analysis said so".
What they should actually build: only the cheap seams. For monolith_to_services: that all access to the catalog goes through a clear interface (no direct reads of its tables), that the catalog has its own tables with no joins entangled with other domains, and a defined contract —all inside the monolith, without building any service—. For second_payments_provider: an abstraction over the payment provider, so that adding the second is a bounded change —with a single real provider for now—. That's reserving the right of way: cheap today, and it turns the future construction (the microservices, the second provider) into something easy when the business asks for it. The avenue is paved when the traffic arrives; today only the strip is reserved.
Summary and next step
In this lesson you synthesized the module: the path between the two abysses is designing the seams at the sensible point. You burned in the phrase that orders it: designing for change is not designing for EVERY imaginable change —it's building the seam only where the change is probable enough to pay for itself, and deferring the rest—. You saw, with the urban planner who reserves the right of way where growth is probable, that mastery isn't reserving everywhere (over) nor nowhere (under), but choosing where. And you measured it: right-sizing costs 43050 against over-engineering's 90610 and the rigid one's 133550 —not a compromise, a dominance—, because it decides future by future with the break-even point of lesson 3, building the probable seams and deferring the improbable ones. You consolidated three critical things: the probabilities are derived from the business's signals (not guessed), the seam isn't the solution (reserve the right of way, don't pave), and right-sizing is a flow that's revised (not even the evolution plan is final).
Before moving on you should be able to: apply the break-even rule future by future to decide which seams to build; explain why the sensible point dominates the two extremes instead of compromising; and distinguish the seam (cheap, today) from the solution (expensive, when the change arrives).
Lesson 8 is the project: you take the role of Mercado's architect facing the launch of a new capability —Mercado Plus, a paid membership— with a roadmap of anticipated changes, and you produce the planned evolution from scratch, on a new case. You're going to right-size the portfolio with your own hands, decide what to build today, what to sacrifice in a prototype and what to defer, and put together the script of how you explain it to the stakeholder. The whole module, executed by you.
Resources
- Neal Ford, Rebecca Parsons, and Patrick Kua, Building Evolutionary Architectures (O'Reilly, 2017) — the module's central book, and in particular its idea of guiding the evolution with explicit criteria (fitness functions) instead of preparing for everything or for nothing. Right-sizing is that idea applied to the seams. In English.
- Eric Evans, Domain-Driven Design (Addison-Wesley, 2003) — the bounded contexts are the natural seams of a system: the boundaries where it's worth leaving the right of way for future extractions. The source of where to put the seams, not just how many. In English.
- Michael Feathers, Working Effectively with Legacy Code (Prentice Hall, 2004) — the manual of seams: what they are technically and why they're the point that makes a system modifiable. This lesson's seam comes from here. In English.
- Martin Fowler, "Design Stamina Hypothesis" (2007) — martinfowler.com/bliki/DesignStaminaHypothesis.html. The sensible design point between under-investing (under) and over-investing (over) —exactly what right-sizing calculates—. In English. The mechanics of recording these decisions (the ADR) and of classifying their reversibility is the sister guide
architecture-decisions.