← The ADLC library
Live debates · 43

Consistency stopped being a preference

Arguments about doing things one way used to be about taste, with a modest payoff in onboarding. Consistency is now a metered input cost, paid on every generation and every review, and the economics of the argument have completely inverted.

Every engineering organisation has had the same argument. Two ways to do a thing, both defensible, neither obviously better. Someone proposes standardising. Someone else points out that standardisation costs a migration and buys nothing users can see. The argument ends in a draft ADR that nobody merges, and the codebase keeps both.

That was a reasonable outcome. The cost of inconsistency was real but small, paid slowly, mostly in onboarding time, and amortised across years. Standardising cost a migration now to save a bit of confusion later, and the discount rate on “later” was high enough that deferring was often correct.

My position: that calculation has inverted, and most teams have not repriced it. Consistency is no longer a preference with a soft payoff. It is a per-run input cost, metered, paid on every ticket, and it compounds through the part of your pipeline that is already the constraint.

Where the cost moved

Under the old model, inconsistency was paid by humans, once per human, at hiring time. A new engineer spends a week working out that the reporting service does configuration differently. Annoying. Bounded. It never happens to that person again.

Under the new model it is paid per generation. An agent working a ticket has to resolve the ambiguity every single time, from scratch, with no memory of resolving it last Tuesday. It resolves it by looking at the code near where it is working, which means the answer depends on where the ticket happens to land. Same organisation, same convention question, different answer, no learning curve that ever flattens.

Then it is paid a second time in review, because a reviewer now has to decide whether the pattern chosen was the right one, which is a slower judgement than checking whether code is correct. And it is paid a third time when the answer was wrong and the change is reworked.

Inconsistency as a preference

  • Paid once per new hire
  • Cost falls as people learn
  • Shows up in onboarding, which nobody measures
  • Deferring the migration is usually right

Inconsistency as an input cost

  • Paid on every generation run
  • Cost is flat forever, no learning curve
  • Shows up in review load and rework, which are your constraint
  • Deferring compounds against you
The same mess, priced two ways. The second pricing is the one that now applies, and almost nobody has redone the arithmetic.

The compression argument

Here is the cleanest way I know to think about it.

Everything an agent needs to know about how your organisation builds software has to fit through a context window, or be retrieved into one, on every run. That is a bandwidth constraint and it has a price attached, in tokens and in latency and in the failure rate when the relevant fact does not make it in.

A consistent codebase compresses. One way to handle configuration means one example suffices, and the example generalises. An inconsistent codebase does not compress: three ways to handle configuration means either three examples plus a rule for choosing between them, or one example and a coin flip.

So consistency is, quite literally, how much of your organisation’s practice fits into the space available. That is not a metaphor about elegance. It is the mechanism by which a divergent pattern turns into a wrong guess turns into a review comment turns into a rework cycle.

And the wrong guesses are not evenly distributed. They cluster in exactly the areas where you have the most history, the most divergence, and the most business risk, because those are the same areas.

Uniform and mediocre beats split and excellent

This is the part people find uncomfortable, so let me state it plainly. If you have a good pattern used in a third of the codebase and a mediocre pattern used in two thirds, converging on the mediocre one is often the better economic decision.

The reason is that the value of a pattern is now the sum of its intrinsic quality and its predictability, and the predictability term got much larger. A mediocre pattern applied everywhere produces output you can review quickly, generate reliably and reason about at scale. An excellent pattern applied in a third of the codebase produces a permanent adjudication cost on every run near the boundary.

I am not saying quality stopped mattering. I am saying the exchange rate between quality and uniformity moved, and the teams that will feel this first are the ones with a long history of thoughtful, locally-optimal decisions made by strong engineers who were never wrong about anything except how many patterns the organisation could afford.

Per generationAmbiguity resolved from scratch, by proximity rather than by policy. No memory between runs.
Per reviewReviewer decides whether the chosen pattern was right, a slower call than whether the code is correct.
Per reworkWrong guesses become a second pass through the constrained stage.
Per incidentTwo retry mechanisms behave differently under load, and the difference surfaces at the worst time.
Four charges on one divergence. Only the last was visible under the old model, which is why the old model tolerated so much of this.

What this means for your migration backlog

Every platform team has a list of migrations that never get funded. Half-finished framework upgrades, two logging libraries, the service that still uses the old auth middleware.

Those items were correctly deprioritised under the old economics and are mispriced under the new ones. They are not cleanup. They are a reduction in the per-ticket cost of every future change in the affected area, and they should be argued for on that basis rather than on craft.

Two practical notes. First, finishing a migration is worth far more than starting one, because a migration at thirty percent has strictly more divergence than not starting at all. If you cannot fund the finish, do not fund the start. Second, the order matters: do the concerns that appear in the most tickets first, not the ones that annoy you most. Configuration, error handling, HTTP clients, authentication and logging show up in nearly every change. The reporting module’s odd date handling does not.

Where this breaks down

Standardisation is a real way to make a codebase worse. The strongest version of the counter-argument: local variation is often correct, because subsystems have genuinely different constraints, and a rule that flattens them makes the reporting pipeline pay for the API gateway’s requirements. Every organisation has a story about the mandated framework that cost a year. I am arguing for fewer patterns, not for one pattern, and the difference matters.

Migrations have a failure rate you should assume is high. I am recommending you fund work that historically gets abandoned at sixty percent, which by my own argument leaves you worse off than not starting. If your organisation has never finished a migration, the honest advice is to fix that capability before using it as a strategy.

A rules file is much cheaper than a migration, and might be enough. You can tell an agent which pattern is canonical without changing a line of code. If that works, my whole argument collapses into a documentation task. My scepticism is that stated rules lose to demonstrated frequency when the two conflict, but I do not have a clean measurement of that, and teams should test it on their own repository before believing me.

I sell a control layer, so discount this accordingly. Everything in this piece points towards standardising and then enforcing, and enforcement is a category we have a commercial interest in. The argument stands or falls on the economics, and you should check the economics on your own numbers rather than take mine.

The tooling may absorb this entirely. If context handling improves enough that divergent patterns get resolved correctly by ownership and recency signals rather than by frequency, then inconsistency goes back to being a taste question. That is a plausible eighteen-month future. I would still standardise, because the review-side cost is paid by humans and does not go away, but I would be less emphatic about it.

The takeaway

The argument about doing things one way was never won on craft, because craft arguments are unfalsifiable and expensive to act on. It does not need to be won on craft any more. Inconsistency is now a metered cost, charged on every generation and every review, in the stage of your pipeline that is already the bottleneck.

If you take one thing into next week: pick the single concern that appears in the largest share of your changes, count how many ways your codebase currently handles it, and put a number on how many tickets touched that concern last quarter. That product is roughly what the divergence is costing you, and it is the first migration argument you have that a finance-minded person will accept.