Picture a team gathered around a conference table, laptops open, a whiteboard behind them scrawled with boxes and arrows. They are discussing a new feature—a modest, seemingly straightforward enhancement to their product. The product manager describes the requirement, the engineers nod, and for a few minutes everyone in the room shares what feels like a single, common understanding. Then the meeting ends, and each engineer walks back to their desk imagining a different system. One is already sketching a database schema change. Another is thinking about a new microservice. A third has decided the whole thing belongs on the client. Everyone is certain they understood the feature. No one can say precisely what the feature is.

Anyone who has spent time building software recognizes this moment. The misalignment is quiet, almost polite—nothing is obviously wrong, and the work moves forward. Code gets written, tests pass, the feature ships. The gaps in understanding surface later, and always at a worse time: during integration, in a confused user’s feedback, or in the cold light of a production incident. The failure, when it is finally traced, turns out not to live in the code at all. It lives in the shared understanding that was supposed to precede it.

Failures of this kind rarely begin at the keyboard. They begin much earlier, in the blurry space between conversation and implementation, between a thought and the artifact meant to hold it. That space is where specifications belong. For most of our history, though, we have treated them as secondary—useful scaffolding at best, disposable paperwork at worst. This essay argues for the opposite instinct: that a system should be designed before it is implemented, with the specification as the primary artifact from which everything else follows.

01 Software Begins as Knowledge

Before software becomes code, it exists as understanding. It lives first as a set of ideas, constraints, and intentions held in common by the people who build and use it—sometimes clearly, more often in fragments, and never entirely finished. The running system we eventually ship is the last form this understanding takes, not the first.

Think of the architecture meeting where a handful of engineers argue about how to scale a service. The whiteboard fills with boxes and arrows, trade-offs are weighed aloud, and someone scribbles a rough API contract in the corner. Or the product conversation where a customer’s half-formed need is slowly turned into a feature, with design sketches standing in for interactions no one has built yet. These moments capture knowledge in every available form—spoken, drawn, written down in fragments. They are the crucible in which a system first takes shape.

Source code is only one representation of that knowledge. It is precise and executable, which is exactly why we come to trust it, but precision is not the same as completeness. Code tells you what happens; it rarely tells you why, or which alternatives were rejected, or what constraints the whole arrangement was built to respect. That context lives elsewhere—in specifications, diagrams, user stories, and the memories of the people who were in the room.

And elsewhere is a fragile place to keep anything. The knowledge scatters across emails, tickets, and comments; it ages, contradicts itself, and drifts out of date. The deeper tension is that understanding is abstract and fluid by nature, while code demands precision and finality. Closing that gap takes deliberate effort: capturing knowledge in a form expressive enough to hold intent and authoritative enough to be trusted. That is the role a specification is uniquely suited to play.

02 Why We Treated Specifications as Secondary

That specifications ended up in a secondary role was no accident. It was the product of real historical forces and hard practical constraints, and understanding them is the only honest way to see why the habit formed—and why it is now worth breaking.

In the early decades, implementation was slow and expensive. Writing code demanded specialized skill and considerable time, so a specification was treated as a planning document: something you produced to avoid costly mistakes before committing to the real work. Get the design right on paper, the thinking went, then move as quickly as possible into building. The document was a means to an end, and the end was always the code.

Requirements, meanwhile, refused to hold still. Business needs shifted, markets moved, technology turned over underneath everyone’s feet. That volatility made detailed specifications feel risky—by the time a document was finalized, reality had often moved on without it. The waterfall model tried to impose order by walling design and implementation into separate phases, but its rigidity tended to produce documentation that was either ignored or quietly out of sync with the system it described.

The backlash was inevitable, and it gave us agile: working software over comprehensive documentation, collaboration over ceremony, responsiveness over plans. As a response to genuine uncertainty, this was entirely rational. But specifications grew lighter, more informal, and often implicit—surviving as conversations, ticket descriptions, and the occasional code comment rather than as anything authoritative.

So documentation drifted. The written description and the running system diverged a little more with every change, and keeping them aligned came to feel like wasted effort when the code was the “real” software anyway. That instinct hardened into a worldview: the specification was a guide or a historical record, never a primary artifact.

None of these choices were mistakes. They were sensible adaptations to the economics of their moment. But it is worth noticing what every one of them shared: each was, at bottom, a response to the high cost of implementation. We treated specifications as disposable because code was expensive, slow, and scarce—and when the thing you are protecting is expensive, you optimize around it. That is precisely the assumption now coming apart.

03 Specifications Are More Than Better Documentation

Up to this point I have deliberately avoided the term Specification-Driven Development, and the omission was intentional. Before naming a methodology, I wanted the problem it answers to be felt rather than asserted. We are too quick, as an industry, to reach for a new process before admitting that the old mental model has run out of room. SDD is not interesting because it asks us to write specifications—we have written specifications for decades. It is interesting because of the role it gives them.

In conventional development, the specification comes first and then politely steps aside. Once coding begins, the center of gravity shifts to the code, and the specification settles into the past as historical context. Ask a developer how the system behaves and they will read you the implementation, because the implementation is assumed to be the most accurate account of itself.

Specification-Driven Development inverts that relationship.

The specification stops being an input to development and becomes the persistent source of truth. Architecture is validated against it. Implementation, increasingly AI-assisted, is generated from it. Tests verify it, documentation explains it, governance protects it. The code becomes one realization of the specification rather than the specification becoming a belated explanation of the code.

The change is subtle, and its consequences are not. The primary work of engineering moves away from producing implementation and toward preserving shared understanding—and once you see it that way, familiar activities quietly change shape. Code reviews become specification reviews. Refactoring becomes the preservation of intent rather than the rearrangement of implementation. Even technical debt starts to look less like badly written code and more like understanding that slipped out of the specification and was never written back in.

This is also why specification-first thinking sits so naturally inside the argument this series has been making. The End of Complexity, Architecture After AI, The Economics of Software Design, and The Human Complexity Budget were each, in their own way, approaching the same realization from a different angle: as implementation becomes abundant, shared understanding becomes the scarce resource. If AI drives the cost of producing code toward zero, then code is no longer the thing worth optimizing around. Clarity is. And clarity is made, contested, and refined in specifications—nowhere else.

What remains is a fair question: is this merely a philosophical reframing, or does it change how software is actually built? The answer depends on something more fundamental than methodology—on what we believe software is in the first place.

The economics underneath all of this are already shifting. For most of our history, implementation was the scarcest and most costly thing we had; today it is increasingly the part a machine can supply on demand. When the most expensive step becomes cheap, the questions worth asking move somewhere else.

Perhaps the question is no longer whether a system should begin with a specification. Perhaps the more interesting question is why we ever believed it could begin anywhere else. If a system is, in the end, an expression of shared understanding, then a specification is not describing the software. It is preserving the understanding from which the software emerges.

We like to say that software is built when the code is written. It would be nearer the truth to say it is built when understanding becomes explicit—and that everything after that is translation.