Contract-First Is Not Big Design Up Front
août 18, 2026Whenever I argue that no integration between two modules should begin without a written, versioned contract, the same objection arrives within minutes: "That's waterfall. That's Big Design Up Front. We're agile — we iterate."
The objection deserves a real answer, because it's conflating two things that are genuinely different — and the difference is exactly where the value lives.
What the objection gets right
Big Design Up Front — the practice of comprehensively designing a system before implementing any of it — deserved its bad reputation. It assumed you could know everything before building anything. It produced specification documents that were obsolete before the first sprint ended. Agile was, in large part, a correction to that failure, and the correction was right.
If contract-first meant "design every interface in the system before writing code," the objection would land. It doesn't mean that.
What contract-first actually asks
Contract-first asks one thing: before two modules integrate, write down what crosses the boundary. What the interface receives, what it returns, what it guarantees under error, what version it is.
For a typical service interface, that is a one-page schema. It takes an hour, maybe two with review. It says nothing about how either module is implemented. Behind the contract, you can iterate, refactor, rewrite, change databases, change frameworks — none of it is the consumer's business, and none of it is constrained.
And here's the part the "it slows us down" objection misses entirely: the contract is what enables parallel work. The moment the contract exists, the consuming team can build against it — mocks, tests, full integration logic — while the providing team implements behind it. Two teams moving at full speed, in parallel, with confidence. Without the contract, one team waits for the other, or both build on assumptions and reconcile in production.
Amazon understood this in 2002, when an internal memo mandated that all teams expose functionality exclusively through service interfaces — no exceptions, no direct access. The discipline felt heavy. It's also what made Amazon's internal services composable enough to become AWS. The cloud industry is, in large part, a consequence of one contract-first mandate.
How I learned it the expensive way
I'll offer my own failure as evidence, because I didn't start contract-first either.
My trading platform, Krachen, began with a single market data provider — one broker API to consume. I knew I wanted a modular architecture, so I structured the Gateway module carefully. But I made one mistake: I built the internal data models around that first provider's response format. The objects flowing downstream carried the broker's conventions — its field names, its precision, its event structures. It felt pragmatic. There was only one provider, after all.
Then I added a second broker. The new API returned different formats, different field names, different event structures. And the Strategy modules downstream expected the first broker's shape. Every mapping I now had to write lived at the wrong level — outside the Gateway, in code that should never have known anything about provider-specific formats.
The fix was painful and instructive in equal measure: I refactored the Gateway around a generic internal model — a formal contract defining what market data looks like inside the system, independent of any provider. Each broker integration now maps to that model inside the Gateway, before anything crosses the module boundary. The Strategy modules see the contract, not the provider. Adding a third broker today would take hours, not days.
The generic model I eventually built was the contract I should have started with. I just didn't know it was a contract yet.
Writing it on day one would have cost an hour. Discovering it through refactoring cost days — and that was in a solo system, where the only coordination cost was my own time. Multiply by teams and the math gets brutal.
The real velocity trap
So let's name the actual trap, because it exists — it just runs in the opposite direction from the objection.
An implicit contract discovered through a production failure costs, on average, one to three days of debugging and coordination per incident. Multiply by the number of consumers affected. Multiply by the frequency of undocumented changes. At any meaningful scale, that math destroys the "we saved an hour by not writing the contract" gain many times over.
The false speed of building without contracts accumulates rework debt until the system becomes too fragile to change quickly at all. That's the velocity trap: optimizing the first week at the cost of every week after.
Contract-first isn't the opposite of agility. It's the precondition for sustaining it.
This is Chapter 11 territory of Architecting the End of Chaos — my book on distributed systems governance, releasing September 2026.
Read the preface free →