DDD · Architecture

A Rule
Evans Never Wrote

Nearly every modern DDD codebase enforces the same rule: an Aggregate may reference another Aggregate only by ID, never by holding a direct object reference. The 2003 book that coined the term Aggregate says the opposite. The person who actually wrote the ID-only rule said so himself, in the same paper, without pretending otherwise.

The rule shows up as a near-universal convention in DDD codebases today, usually stated flatly, no caveat attached: another Aggregate is referenced by ID, an object reference is treated as a modeling mistake. It reads like something straight out of the source material. It isn't.

The Rule as It's Practiced

One codebase's version: "Another Aggregate is referenced only by ID (never by object reference)" — and, restated in its own summary table, "An object reference creates coupling — keep only the ID." Search any recent DDD tutorial, talk, or reference architecture and some phrasing of the same rule shows up almost immediately, usually presented as settled, foundational doctrine.

What the 2003 Book's Own Rule List Says

Eric Evans' Domain-Driven Design lays out its Aggregate rules as a numbered list, translating the concept into implementation constraints. One of the seven items reads, in full and without qualification:

"Objects within the AGGREGATE can hold references to other AGGREGATE roots." (p. 92)

Not a hedge, not an aside — a listed rule, sitting between "only Aggregate roots can be obtained directly with database queries" and "a delete operation must remove everything within the Aggregate boundary at once." The book that defined what an Aggregate is explicitly permits exactly what today's convention forbids.

Not a close reading

This isn't a case of stretching an ambiguous sentence to make a point. The book states its Aggregate rules as an enumerated list specifically so implementers know what's actually required. Direct object references between Aggregate roots are on that list, as something permitted.

Where "By ID Only" Actually Comes From

The rule everyone follows today traces to Vaughn Vernon's 2011 paper Effective Aggregate Design, Part II — and Vernon doesn't claim it as an Evans rule. He opens the relevant section by citing Evans directly and accurately: "[DDD] states that one aggregate may hold references to the root of other aggregates." He then adds his own, separate rule on top of it:

"Rule: Reference Other Aggregates By Identity — Prefer references to external aggregates only by their globally unique identity, not by holding a direct object reference."

Vernon isn't correcting a misreading of the 2003 text. He's reading it correctly, agreeing that it permits object references, and then arguing that permission shouldn't be exercised — for reasons the original book never had occasion to consider.

Why the Stricter Rule Won

Vernon's own reasoning, from the same paper, comes down to two concrete costs a direct reference imposes that an ID doesn't:

  • Transaction-boundary safety. "Both the referencing aggregate and the referenced aggregate must not be modified in the same transaction. Only one or the other may be modified in a single transaction." A live object reference makes that mistake easy to make by accident — the other Aggregate is right there, one method call away. An ID forces an explicit Repository lookup to reach it, which is exactly the moment a developer notices they're about to touch a second Aggregate and reconsiders.
  • Cost of what gets loaded. "Aggregates with inferred object references are... automatically smaller because references are never eagerly loaded. The model can perform better because instances require less time to load and take less memory." An object reference invites a persistence framework to eagerly or lazily pull in a whole second Aggregate graph just to satisfy a field type; an ID is a string.

Two Rules, One Principle Neither Contradicts

The deeper constraint both rules are protecting was never in dispute — it's Evans' own, stated a few lines above the disputed one: "the invariants applied within an AGGREGATE will be enforced with the completion of each transaction," implying, though never quite legislating, that a transaction's job is to keep exactly one Aggregate consistent. Vernon's identity-only rule doesn't revise that principle; it closes a specific loophole — a direct reference — that made violating it too easy to do without noticing. What looks, on the surface, like a codebase disagreeing with the book it claims to follow is actually the book being followed at two different points in the same argument's history: the constraint is Evans', and the mechanism that makes the constraint hard to break by accident is Vernon's, built consciously on top of a permission Evans left open.

Further reading

Eric Evans, Domain-Driven Design: Tackling Complexity in the Heart of Software (Addison-Wesley, 2003), Chapter 6 · Vaughn Vernon, "Effective Aggregate Design, Part II: Making Aggregates Work Together" (2011) · backend-service-playbook/docs/architecture/tactical-ddd.md