David WalshSubscribe
Thought leadership

Architecting for change, not for certainty

Most platforms rot because they were built for a future that never arrived. Here's the heuristic I use to stay loose without going vague.

Most platforms rot because they were built for a future that never arrived. A team picks a database for the load they expect in three years, a queue for a partner integration the sales pipeline insists is imminent, a billing model for the pricing tier marketing is still workshopping. Then the future shows up wearing different clothes, and the shape fights back. The cost of being wrong about the future isn't paid at the moment of the decision. It's paid every week, forever, in friction.

The premise

Architecture is the act of making some things easy and other things hard. That's the whole job. Every line drawn between two services, every schema committed to, every framework adopted — each is a statement about which future moves should be cheap and which can be expensive. Trades compound. By the time anyone notices the shape, the shape is the system.

The instinct most architects are trained on is to pick the right trade. Read the requirements, project the load, study the domain, choose the architecture that fits. It's a comforting story and it's mostly wrong. Requirements drift. Load comes in shapes nobody projected. Domains turn out to be three domains in a trench coat. The "right" architecture for a system you fully understand is rarely available, because by the time you fully understand the system it's running in production and nobody's allowed to rebuild it.

The goal is not to pick the right architecture. The goal is to make the inevitable wrong ones cheap to correct.

The certainty trap

The failure mode here is a kind of architectural stage fright. Someone — an architect, a stakeholder, a vendor slide — produces a forecast. The product will need to support fifty thousand concurrent users. It will be white-labelled for partners. It will need GDPR-equivalent controls in three more jurisdictions. The forecast becomes the requirement, the requirement becomes the constraint, and the constraint becomes the shape of the next two years of work.

Then the future ignores the forecast, which it usually does. The fifty thousand users are eight thousand and they all want a feature nobody planned for. The white-label deal collapses in legal. The new jurisdiction wants something the existing GDPR pattern actively can't model. And now there's an architecture optimised for a world that doesn't exist, and the team is paying interest on a loan nobody remembers taking out.

I spent three years architecting around a constraint that didn't exist.

That line — the title of a separate piece on this site — names the trap precisely. Certainty feelslike rigour. Drawing a precise box around a future requirement looks like the work of a serious engineer. It is, in fact, the opposite. Rigour is admitting you don't know, and designing accordingly.

The three-question heuristic

Before locking any decision of consequence — a database, a service boundary, a public API shape, a vendor — three questions are worth asking, out loud, in the room:

The first two are familiar. Most architectural write-ups are some version of "here's what this makes easy, here's what it makes hard." The third is the one teams routinely skip, and it's the one that matters most.

Reversibility is the hidden axis

Reversibility is the most underrated property of any architectural choice. A decision that's eighty percent right and fully reversible beats one that's ninety-five percent right and stuck. The eighty-percent decision lets the team find out it was wrong, cheaply, and try again. The ninety-five-percent decision is a trap with good marketing.

Amazon's one-way-door / two-way-door framing is useful as far as it goes, but the world isn't a clean binary. Reversibility is a spectrum, and most decisions sit somewhere awkward in the middle. The useful question isn't "is this reversible?" but "what would it cost — in days, in dollars, in customer trust — to reverse this in eighteen months?"

A decision tends to be reversible when the blast radius is small, the data can move, and the contract at the seam is honest. A decision tends to be irreversible when it leaks across service boundaries, when data is welded to a particular shape, when undoing it would require coordinated changes across teams who no longer remember why the original decision was made.

Reversibility gets dismissed as a hedge. It isn't. It's the cheapest insurance policy in software.

A worked example: auth

Consider authentication. This is the canonical "it's a solved problem" decision, and it's the one the most teams get wrong. The usual write-ups compare features — SSO support, MFA options, session management, social providers. It's more useful to compare reversibility:

const decisions = {
  "rolled our own":     { reversible: "painful",  fits: "big teams, hard regs" },
  "saas provider":      { reversible: "medium",   fits: "most teams" },
  "library in-process": { reversible: "cheap",    fits: "early stage" },
};

None of these is universally right. Each makes different things easy and hard. But for a team of four on a product that hasn't yet found its shape, the third row is almost always the answer — not because it's technically superior to a SaaS provider, but because if the team is wrong about who the users are, what needs authenticating, or which compliance regime they'll end up under, they can rip it out in a sprint.

A SaaS provider locks the product to someone else's data model, session semantics, and pricing curve. Rolling your own locks it to a permanent maintenance bill and an attack surface nobody wants to own. Both are defensible. But both cost weeks-to-months to undo, and neither teaches the team anything new about the product.

The in-process library reveals what shape the auth actually wants to be, while the team still has the freedom to change its mind. Once the shape stops moving, it can be promoted to whichever permanent home actually fits.

A second example: the data shape

The same logic applies, more painfully, to data. The decision that is almost never reversible is the shape of the rows in the most important table. Pick the wrong primary key, model the wrong invariants into the schema, denormalise too aggressively or too cautiously, and the product pays for it for as long as it exists. Migrations are not free, and large migrations on live systems are not even close to free.

When reversibility is genuinely poor, the right response is the opposite of the auth example: slow the decision down. Spend the extra weeks before committing. Build a thin facade in front of the storage layer so the underlying shape can change without rippling outward. Treat the schema as a published API, because functionally that's what it is — every report, every integration, every analytics pipeline becomes a consumer the moment it's pointed at the table.

The heuristic still works, it just changes which lever gets pulled. When something is cheap to reverse, decide fast and learn from the rollback. When something is expensive to reverse, invest in either making it cheaper to reverse — usually via a seam — or in being meaningfully more right up front.

Teams that can change their minds

A reversible architecture in the hands of a team that can't change its mind is just an unused option. The technical seam doesn't help if the org won't pull it.

The teams that get this right tend to share a few habits. They write decisions down — short ADRs, dated, with the trade-offs visible — so future versions of the team can re-examine the original logic without reconstructing it from folklore. They run small, time-boxed reversibility tests: deliberately flipping a feature flag off, swapping a provider in staging, running the system on the backup database for an afternoon. They keep the contracts at their seams honest, with consumer-driven tests that fail loudly when a "small" internal change leaks. And — this one is the hardest — they treat the act of reversing a decision as a normal piece of work, not an admission of failure.

Teams that can't reverse decisions calcify around them. The original choice becomes politically expensive to revisit, then technically expensive, then forgotten. The system inherits all the constraints with none of the reasoning. Architecting for change is partly a property of the code; it is mostly a property of the people who own the code.

Closing notes

Architecting for change is a practice, not a pattern. There isn't a diagram to copy off a slide. It's the habit of asking, every time something is about to be locked in: if we're wrong, how do we find out, and how much does it cost? Sometimes the answer is "cheap, and quickly," and the team should move fast. Sometimes the answer is "ruinous, and never," and the whole room should slow down until the certainty has actually been earned.

Done consistently for a year, systems get quieter. So do the meetings. The forecasts keep being wrong — they always are — but the cost of being wrong stops being the thing that defines the roadmap.

Build for the future you can change your mind about. That's the only one that ever actually shows up.