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, whether that is a module which may not import another, a layer which may not know what sits above it, or 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. Alistair Cockburn’s Hexagonal Architecture and Jeffrey Palermo’s Onion Architecture gave it a geometry, and Robert Martin, in a 2012 post that presented itself explicitly as an attempt to integrate those and several others, gave it the name Clean Architecture and its best-known diagram, concentric rings in which dependencies point inward, toward the stable business rules, and away from the volatile frameworks and databases at the edge. Beneath the differences in costume, the ideas are two: 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 deserve to be taken seriously, and I largely take them. What is less often noticed is that they share a premise with the philosophies they criticize: that the code is written by a person, that this person’s attention is the scarce resource, and that the architecture’s job is to spend it 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. Human attention is as scarce as it ever was, but it has moved: the hours a person once spent writing a change now go to deciding whether a change written by something else is right, and there are many more changes to decide about. A boundary used to pay for itself by making code easier for a person to write and to read. It now pays for itself by making a change cheap to check, by a machine wherever possible and by a person only where nothing else will do. 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 payments service. Somewhere in the repository is a rule: money crosses the boundary of the payments module as an integer count of minor units, never as a floating-point number, because floating-point arithmetic rounds in ways that eventually cost someone a cent. 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 compute fifteen percent off as a float and pass it through, the tests will pass because none of them happens to land on an amount that rounds badly, and the boundary will have stopped existing without anyone present to notice. If instead the module accepts only a money type whose sole constructor takes an integer, the build fails, the agent reads the error, and it performs the rounding explicitly, in minor units, before the value reaches the boundary, because the careless path was closed. 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. 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.
It helps to see one. On the page, a Form is a short document kept in the repository beside the interface it describes. For the payments module it might list the four functions that make up the public surface and the errors they may raise; two invariants, that every amount is an integer count of minor units and no float crosses the boundary, and that no refund exceeds the charge it reverses; one hidden decision, that callers never learn which processor sits behind the module; and, beside each invariant, the check that fails when it is broken. Everything the page leaves out is implementation, and may be thrown away and written again.
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, a term Neal Ford, Rebecca Parsons, and Patrick Kua introduced in Building Evolutionary Architectures for an objective assessment of some architectural characteristic. Their account admits manual checks; Eidos adopts the term in its strictest form, meaning automated, deterministic and 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 carry the weight, 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.
Maximal convention and human-designed seams can look as though they pull against each other, since a human-designed seam is structure that no framework asked for. They divide the territory between them. Wherever the framework has an opinion, its convention is a Form that someone else has already written, and it is adopted as it stands. A Form of one’s own is written only where the framework falls silent and the system’s particular rules begin. What separates such a Form from the bespoke structure condemned above is that it is written down, and that a machine rejects whatever violates it; neither was true of the architecture in the senior engineer’s head.
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 answers a changed economy rather than expressing a preference in style. 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 therefore has to be enforced against itself, and enforced the way everything else in Eidos is: by a check that fails the build when any invariant listed in a Form has no gate behind it. A Form that cannot pass that check is the old disease returning, and the build reports it before anyone has to.
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 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.
The third vulnerability is of the same kind, and it sits underneath the name. That people must design the Forms rests on models being poor at interface design, which is likewise a fact about the current generation. If a model comes to design a deep module as well as a senior engineer does, the drafting moves to the machine, and what stays with a person is narrower: deciding that a Form is the right one, and answering for it. The Form survives that change. An interface and its invariants are no less the durable thing for having been drafted by a machine, and they still have to be measured by something other than their author.
Mechanical enforcement survives all three, since verification stays cheap to demand no matter who writes the code, who designs the interface, or how well either of them reads, which is why this essay leans hardest on it. It has limits of its own (which rules deserve a gate, who guards the gates, and what a passing gate proves), and they are taken up in a companion essay.
Planting the flag
The arrangement is being approached, in pieces, from several directions at once. Matt Pocock, writing on how to make a codebase agents can work in, arrives at deep modules by the route this essay takes: “Deep modules create a natural seam in your codebase. You carefully control and design the interface. The implementation inside? Delegate that to AI.” His enforcement, however, is a test suite rather than a gate, and he concedes that in TypeScript “it’s not easy to enforce these boundaries.” The Nx team, coming at it from the build side, ships module-boundary constraints that fail at lint time, which is mechanical enforcement without a theory of where the boundaries ought to go. Mathias Biilmann, meanwhile, has proposed “Agent Experience” in deliberate echo of DX, though his concern is agents as users of a product (its APIs, its documentation, its sign-in flow) rather than as contributors to a codebase, which makes it a neighbor of this argument. The first two each hold one leg of the arrangement; nobody, so far as I have found, holds all three, and the vocabulary around them (agent-native, agent-ready, agent-friendly) has multiplied without settling. There is no book, no canonical diagram, and no name the industry has agreed to.
The obvious objection, and a fair one, is that naming an idea is marketing, and that an essay which announces a name is asking for credit it has not yet earned. I accept the second half of that. Clean Architecture did not prevail over Hexagonal and Onion on merit, since Martin’s own post presented it as their integration, and whether it prevailed everywhere is debatable. Where it did become the default, it did so, as best I can tell, on a name, a diagram, and an author willing to plant a flag, and it was the book behind the name that kept it there. A similar opening exists now, and it will not stay open indefinitely, which is the case for naming this arrangement before it has a book.
So I’m calling it Eidos.
The name is Plato’s word for Form, and the metaphor has been at 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.
This essay has two companions: The Limits of a Gate, on what mechanical enforcement cannot do, and On the Name Eidos, on where the word comes from. The specification continues here.