What is an aggregate?
An aggregate is a domain object that depends on another root domain object. It has its own meaning, but it belongs to a larger conceptual unit inside the system. It should not be confused with a collection: a collection is only a list of values, while an aggregate represents a domain concept with behavior and rules.
Just as a domain object is not a direct mirror of the database, aggregates are not either. They may reflect persisted information, but they are not merely primitive structures without context.
What do aggregates enable?
Using aggregates helps limit the number of direct interactions between models. The root object does not need to understand the details of its aggregates; instead, it delegates to them the actions that belong to their part of the domain.
That supports the Law of Demeter, reduces coupling, and helps prevent collateral damage when implementations change over time.
How should we persist them?
By definition, only root objects should own a Repository. All persistence operations for the root should go through that repository, which is also responsible for managing its aggregates.
When one root relates to another root, however, we are no longer talking about an aggregate in the strict sense. We are talking about two separate roots, each with its own Repository.
That is where a Domain Service comes in. This service receives the required repositories through dependency injection, retrieves the relevant roots, performs the required domain operations, and then persists the changes.
The root object that references the other should not store the whole aggregate, but rather a list of identifiers.
Conclusion
The aggregate pattern lets us compose domain objects under a root while reducing coupling and delegating responsibilities. From a persistence point of view, two cases matter:
- If the related object is another root, it is better to work with identifiers and coordinate persistence through a Domain Service.
- If it is an internal domain object, it should be persisted through the root object’s Repository.