← Writing

Eidos: An Architecture for Cheap Code

For roughly fifty years, the central question of software architecture has been where the boundaries should go, and the answers have differed in vocabulary considerably more than in substance. By a boundary I mean something specific: a line in the codebase that changes are not permitted to cross freely — a module that may not import another, a layer that may not know what sits above it, an interface behind which the implementation is nobody else’s business. David Parnas argued in 1972 that we should draw these lines around whatever is likely to change, hiding each volatile decision behind an interface so its blast radius stays contained. The Gang of Four gave that instinct a pattern catalog. Robert Martin scaled it up into concentric rings and called it Clean Architecture — dependencies point inward, toward the stable business rules, and away from the volatile frameworks and databases at the edge. Hexagonal, Onion: restatements of the same two ideas in different costume. Manage your dependencies, and decompose by rate of change.

The dissenters, to their credit, were arguing about the same thing from the other side. The Rails school — David Heinemeier Hansson’s “omakase” position, that a framework’s opinions should be accepted the way one accepts a chef’s menu — held that the framework is the architecture, and that the abstraction insurance Clean Architecture sells is a premium paid daily against a fire that rarely comes, since nobody actually swaps their database. John Ousterhout, in A Philosophy of Software Design, observed that complexity comes from shallow abstractions rather than impure ones — interfaces whose cost to learn approaches the value of what they hide — and that a pass-through layer, an interface with one implementation, a DTO mapped between two identical shapes, is cost without benefit. The vertical-slice camp noted that most changes are feature-scoped, so organizing by layer guarantees that each change touches five files across five directories. These critiques are worth taking seriously, and I largely do. But it’s worth noticing that they share a premise with the philosophies they criticize: that the scarce resource is a human’s attention, and that the architecture’s job is to spend that attention well.

As of quite recently, that premise no longer holds, and the consequences are worth working through carefully.

What cheap code changes

Large language models have made code production nearly free. This inverts the cost–benefit ledger of every architecture philosophy at once, though not uniformly, and the details matter. Three observations follow, and the argument of this essay is that a particular architecture falls out of them.

The first observation concerns enforcement. Consider an agent asked to add a discount feature to a web application. Somewhere in the repository is a rule — controllers must not query the database directly; that work belongs to the service layer. If that rule lives in a CONTRIBUTING.md the agent was never shown, or in the review instincts of a senior engineer who now approves forty agent-authored pull requests a week, the agent will violate it, the query will work, the tests will pass, and the boundary will quietly cease to exist. If instead the rule is an import-linter contract — a machine-checked declaration that the controllers package may not import the persistence package — the build fails, the agent reads the error, and it routes the query through the service layer, not out of good citizenship but because that was the only path that compiled. The rule is identical in both cases. The difference is that one of them exists. Prose guidelines were always a weak enforcement mechanism; they become a dead letter when the author of most changes generates faster than humans can review.

The second observation concerns convention. A framework with strong opinions means less context is required to make a correct change — and the agent has seen a million codebases that share those opinions. Convention-over-configuration was designed to make any Rails developer productive in any Rails app; it has, somewhat accidentally, optimized for making any model productive in any Rails app. The philosophies that suffer are the ones in the middle: bespoke, semi-principled structures that are neither conventional enough for a model to pattern-match nor mechanical enough to reject violations automatically. A hand-rolled, clean-ish architecture that lives in a senior engineer’s head is close to the worst possible input one can hand a coding agent. The agent cannot read anyone’s mind, and it does not attend code review as a learner.

The third observation concerns design, and it is here that some vocabulary becomes necessary. Ousterhout’s deep module — a large volume of implementation behind a small, carefully designed interface — turns out to be a nearly ideal unit of work for an agent: minimal surface area to understand, internals hidden, behavior lockable with tests at the boundary. Designing deep modules, however, requires precisely the judgment models remain weakest at. So the labor divides: humans design the durable thing — the interface, its invariants, the decisions deliberately hidden behind it — and agents produce implementations of it, cheaply and repeatedly. I want a name for that durable, human-designed thing, because the rest of this essay is about it. I’ll call it a Form: it is what stays real about the system while implementations come and go, and an implementation is correct exactly insofar as it conforms to it. The reader who hears Plato in that word is hearing correctly, and I’ll return to why.

The synthesis

Each of the three observations demands a commitment, and the three commitments together are the architecture.

From the second observation, maximal convention. Prefer the boring, well-trodden way of doing things, because the contributor writing most of the code has a prior trained on millions of repositories, and that prior does free work wherever the codebase matches it. Structural novelty is now a cost paid on every change, indefinitely, and should be treated accordingly.

From the first observation, mechanical enforcement. Any rule that matters must fail deterministically. The established name for such a check is an architectural fitness function — Neal Ford, Rebecca Parsons, and Patrick Kua’s term, from Building Evolutionary Architectures, for an assessment of an architectural characteristic. Their definition admits manual checks; Eidos adopts the term in its strictest form — automated, deterministic, blocking. A compile error, a lint rule, a dependency-graph assertion, a CI gate: if a boundary is not guarded by one of these, it is not a boundary. It is a suggestion, and suggestions do not survive contact with an agent working in a loop.

From the third observation, human-designed seams. Michael Feathers gave us the word seam — a place where behavior can be altered without editing the code at that place — and the seams are where the Forms live. Deciding where they go, which interfaces are load-bearing, which decisions get hidden: this is the remaining irreducibly human work, promoted from style advice to something closer to the senior engineer’s primary job description. Humans author the Forms; agents fill them; fitness functions verify the fit.

None of these ideas is new, and I want to be careful not to claim otherwise — the lineages run through Parnas, Feathers, Ford, Ousterhout, and the Rails school in roughly equal measure. What is new is the claim that this particular arrangement of them is not a style preference but a response to a changed economy. The winning architecture is no longer the one with the best arguments. It is the one where correctness is cheapest to verify.

What would make this wrong

Before planting anything, I should say what would falsify the argument, because two of its parts are more dated than they look.

The first vulnerability is overhead. Eidos asks for artifacts — Form documents, gate registries, checks that verify the registry itself — and overhead is exactly how Clean Architecture’s ceremony began: as guardrails somebody argued were worth their cost. If the documents come to outnumber the invariants they guard, Eidos will have failed in the same way its predecessor did, with better vocabulary. The discipline has to be enforced against itself: a Form with no fitness function behind it is the old disease returning, and should be deleted on sight.

The second vulnerability is that maximal convention rests on an empirical claim about models — that conventional structure is cheaper for them to work in than bespoke structure — which is true today, and measurably, but is a fact about the current generation of models rather than a law. If context handling improves to the point that a model reads an idiosyncratic codebase as fluently as a conventional one, the convention argument decays into ordinary taste. I would note that mechanical enforcement survives both failures — verification stays cheap to demand no matter who writes the code or how well they read — which is why this essay leans hardest on it. But the reader deserves to know which parts of the argument are load-bearing and which are dated.

Planting the flag

This synthesis is currently being rediscovered, independently and in fragments, across the industry. One practitioner writes about designing module seams so the implementation inside can be delegated to AI. Another team encodes architectural rules into a build graph so they fail deterministically rather than living in reviewers’ heads. A third has begun cataloging practices under the banner of “Agent Experience,” a deliberate echo of DX. The terms multiply — agent-native, agent-ready, agent-friendly — but none has stuck: no book, no canonical diagram, no name the industry has agreed to.

That vacuum will not last. Clean Architecture did not defeat Hexagonal and Onion on merit; the three are close to isomorphic. It won, as best I can tell, on a name, a diagram, and an author willing to plant a flag. The same window is open now, and it is closing.

So I’m calling it Eidos.

The name is Plato’s word for Form, and the metaphor has been doing quiet work throughout this essay. The Form — the human-designed interface, its invariants, its hidden decisions — is what is real about the system. Implementations are material copies of it, produced by a craftsman who is capable, tireless, and fallible. Plato had a name for that craftsman: the demiurge of the Timaeus, who builds the world by copying the Forms as faithfully as the material allows. It took the Gnostics, centuries later, to conclude that the craftsman was flawed and his copies could not be taken on faith. Software has arrived at the economy this metaphysics describes: the Form endures and is expensive, the copies are cheap and disposable, and the measuring — the fitness functions, the gates — is the entire difference between a philosophy and a hope.

The specification, and the systems that demonstrate it, continue here.