The Model Is Not the Bottleneck: Domain-Driven Design as Agent Infrastructure

For the past two years the standard explanation for why coding agents underperform inside enterprise systems has been capability. The model needs a larger context window, a better retrieval layer, a more recent training cut. That explanation has stopped being useful. Agents perform well in greenfield repositories and small services, and they degrade sharply in systems that have been in production for four or five years. The variable that changes between those two cases is not model quality. It is whether the codebase has ever decided what its own words mean.

Ambiguity, Not Ignorance

Consider a routine request in a mature system: add a status field to an entity and expose it through an existing endpoint. In a four-year-old codebase, that entity is likely to exist already under three names, introduced by three teams in three quarters, none of them ever retired. The agent produces a fourth. It writes a translation layer where a direct call was correct, or it calls straight through where translation was the entire purpose of the boundary. It renames a term that a neighboring service publishes and owns.

None of these are knowledge failures. Each one is the model answering a question the system itself has never answered. Where the repository holds several plausible answers, the agent selects one. The selection compiles, passes the existing tests, and reads well in review. It is locally valid and globally wrong, which is the most expensive category of defect an organization can manufacture at speed.

The measurement evidence points the same way. In a randomized controlled trial published by METR in July 2025, sixteen experienced open-source developers worked through 246 real issues in repositories they knew well. Task completion took 19 percent longer when AI tools were permitted, and the participants still believed afterward that they had been roughly 20 percent faster. The result has been contested on sample size and has since been revisited, and the interesting part was never the headline number. It is the setting. The slowdown appeared specifically in mature codebases maintained by people who understood them, which is the exact environment where the answers an agent needs live in a maintainer's head rather than in a file.

The Strategic Half

Eric Evans published Domain-Driven Design in 2003. Martin Fowler, who wrote the foreword to that book, spent the following decade making its strategic vocabulary usable by teams that were never going to read six hundred pages, most durably in his 2014 treatment of bounded contexts. His framing of the pattern is worth restating precisely, because it is the part that matters now: large models are handled by dividing them into bounded contexts and by being explicit about the relationships between those contexts.

Two decades on, the strategic half of DDD has aged considerably better than the tactical half. Entities, repositories, and aggregates arrived in a particular object-oriented moment and have been partially absorbed, partially argued with, and partially replaced. Ubiquitous language, bounded contexts, and context mapping have not been improved on, because the problem they address is not a technology problem. It is the problem of a large organization holding several incompatible meanings for the same word and never saying so out loud.

What has changed is the audience. Ubiquitous language was designed to remove the translation step between domain experts and the engineers writing code. It now has a second consumer, and the second consumer is not human. An agent has no institutional memory, no hallway conversation, and no sense of which of three competing names the team actually uses. Everything it needs has to be present in the artifact it is pointed at.

That shifts what these artifacts should contain. A glossary that lists approved terms is a starting point. A glossary that records the deliberately rejected synonyms is worth considerably more, because rejection is where the decision lives. Recording that the domain uses Job Offer tells an agent very little. Recording that Posting, Listing, and Opening were considered and refused tells it what to do the moment it encounters those words in code it did not write.


The Twelve-Factor Precedent

There is a clean precedent for what has to happen next, and it is not an AI precedent.

When Adam Wiggins and the Heroku team published the twelve factors in 2011, they invented nothing. Every one of those factors described something competent operators already knew: keep configuration out of the codebase, declare dependencies explicitly, treat backing services as attached resources, keep development and production close. The contribution was not the knowledge. The contribution was moving that knowledge out of individual heads and into declarative form, in the repository, where an automated consumer could act on it without asking a person. Portability followed from that, and so did the entire cloud-native tooling generation that assumed it.

DDD is at the same point. Its strategic artifacts are almost always tacit, or worse, they sit as a diagram in a wiki that stopped being true eighteen months ago. Neither form is readable by the thing now writing most of the code. The move is the same one Heroku made: take the model out of heads and slide decks, put it in the repository that owns the code, and version it in the same commit as the change it describes, so that a change to the model and a change to its definition arrive in the same pull request. Declarative meaning rather than declarative runtime.

Ownership at the Boundary

Four questions have to be answerable from the repository itself before an agent edits anything in a large system. Which context am I inside. Which terms does this context own. Which terms arrive from elsewhere and are therefore not mine to rename. Who breaks if I change this.

A context with a written glossary answers the first three. The fourth requires the context map, and this is the artifact almost no organization holds in machine-readable form. The practical requirement is that every relationship between two contexts is declared from both ends, naming the direction of the call, the model that wins when the two sides disagree, and the integration pattern in use. Two declarations of the same relationship either agree or they do not. Disagreement becomes a check that fails in CI rather than an incident discovered in production.

One rule keeps this from decaying. The portfolio-level map is generated from those declarations and never authored. Any map of a system with more than a handful of services that is maintained by hand is stale on the day it is written, and a stale map given to an agent is worse than no map, because the agent will trust it.

The Cost of Deciding

Engineering work has always split into deciding what should change and carrying that decision into files. The cost of the second half has collapsed. The cost of the first half has not moved.

That has a direct budget consequence. Most organizations nominally reserve some share of engineering capacity for debt reduction and rarely spend it, because the mechanical cost of a large refactor never fit inside a quarter. That price has changed. What has not changed is the analysis that must precede the refactor, which means the binding constraint has moved from execution capacity to decision capacity. Organizations that treat agents purely as an execution multiplier, without raising their rate of architectural decision-making, will produce ambiguity faster than they resolve it.

What This Does Not Solve

Boundaries are not models. A context map settles where a context ends and how it speaks to its neighbors. Inside the boundary, ordinary code still permits an invalid object to be constructed and persisted. Value objects, aggregates, and enforced invariants are a separate and later body of work.

Declarations drift. Any description of a system maintained by hand diverges from the system. These artifacts hold only when a check runs automatically and files each discrepancy as work, against the repository that owns the incorrect side.

Not every subdomain earns this. Generic and supporting subdomains rarely justify the modeling effort. Concentrate it where the competitive logic of the business actually sits.

Language discipline is organizational. If three business stakeholders use three words for one concept, engineering will encode three words. No tooling resolves that upstream.

Practice

  1. Maintain one glossary per bounded context, in the repository that owns the code, recording both the accepted term and the synonyms that were rejected.
  2. Declare every relationship between contexts from both ends, naming direction, owning model, and integration pattern.
  3. Generate the portfolio-level context map from those declarations and treat it as disposable output.
  4. Run the consistency check automatically at three moments: when a boundary declaration changes, when a repository is onboarded, and before any change to something another context consumes.
  5. Separate authorship deliberately. Engineers decide and review. Agents carry the decision into files. Direct review attention to boundaries and ownership rather than to line-level style.
  6. Track the ambiguity itself. Synonyms retired and boundary disagreements resolved per quarter is a more honest readiness measure than volume of generated code.

None of this is a new methodology. It is a twenty-year-old one, written down in a form a machine can read. The models will keep improving, and no amount of that improvement will resolve the ambiguity al

About the author

Lucas Hendrich
CTO at Forte Group

You may also like

Transform AI into a Scalable Delivery Capability

83% faster delivery. Under 10% rework. See exactly how Xceptor got there.