Aggregate Pattern

I’ve recently done some reading on DDD and Aggregates in particular. Since many people struggle to understand the pattern, I decided to try to explain it myself.


Imagine that you’re writing yet another e-commerce application and you’re tasked with writing the all-important Order class:

Until the order is packed and ready to ship, customers are allowed to add a position to it:

Now, the business has asked you to limit the possibility to order more than 100 hundred items or for more than 5000$. How do you ensure that these criteria are met, considering the fact that you’re working in a concurrent environment and using a relational database?

Aggregate Pattern

This is a classic usage example of the famous Aggregate Pattern. Although some try to identify aggregates by looking for matching domain concepts, the pattern’s real purpose is to help you ensure transactional consistency between your entities. We’re doing this by deeming one of the entities responsible for ensuring the consistency and performing persistence operations just on this entity. We call such entity an aggregate root. Any other entities, that are “ensured” consistent have to be saved in a single transaction by saving the aggregate root itself.

Applying this to our example, we could say that the Order class should be an aggregate over the OrderPosition class. This implies the following:

  • the Order class is responsible for ensuring the maximum amount of positions and their maximum balance
  • the Order class requires some concurrency mechanism e.g. optimistic locking (aka versioning)
  • there will be an OrderRepository class in the system, but not an OrderPositionRepository class
  • the addPosition operation has to be performed in a transaction

One Aggregate Per Transaction

There’s a good rule of working with aggregates, which says that we should not update more than one aggregate per transaction. It makes perfect sense. Look, if I’m saying that consistency rules lie within the aggregate, then I should be able to save only this one, single aggregate and everything should stay consistent. If that’s not the case, maybe I’m missing an “uber-aggregate” on top of the two that I want to update in a single transaction. Or maybe these rules don’t call for transactional consistency at all?

The rule of one aggregate per transaction has also a usability argument on its side. Imagine the following scenario:

If our users are trying to deal with the same aggregates at the same time, the risk of having a failed transaction grows. The User 2 could prevent the two other users from saving their work and, at the same time, any of the two other users could prevent User 2 from saving his work. That’s not a desirable state of things. By limiting the transactions to one aggregate, we reduce the risk of failed concurrent transactions and therefore improve the usability of our application.

Keep The Aggregates Small

The rule above and the way programmers think combine in a pretty strong force towards big aggregates. Let’s say that someone added a status field to the Order class:

(Let’s avoid the discussion whether such enum is a good idea. We just need an example.)

The business asks you to change the status to PAID once 99% of the order value is paid, to IN_DELIVERY once the guy at the warehouse starts to fill the parcels, and to COMPLETED once all parcels are delivered. Does that mean that the Order class should now take care of payments, parcels, and tracking the guy at the warehouse? The resulting aggregate would be a giant class with lots of responsibilities, just for the sake of maintaining consistency. Also, the performance would suffer badly and the risk of a failed transaction grow significantly. That’s a pretty extreme vision but it shows the limits of the Aggregate pattern applicability.

Eventual Consistency

Things are usually not that bad. If you go and ask the business whether it’s okay for the order status to be updated a few seconds after the payment has been received or the parcel delivered, they will most likely answer positively. Programmers often envision temporary lack of consistency as something evil and dangerous. That’s a nerd point of view. When the business guys say consistent, they usually mean eventually consistent and often it could be even later than in a few seconds.

Therefore, talk to the business guys and embrace eventual consistency when the domain allows it, to keep your aggregates small and your code simple.

Reference by ID

Taking the concepts above even further, if we only want to update one aggregate per transaction and we strive to keep the aggregates small, one could employ the practice of referencing other aggregates only by ID. It further reduces the aggregate, as we’re keeping an ID instead of an object, and allows for better scaling, as we’re no longer forcing ourselves to load multiple aggregates in the same database query. And we’re less tempted to update multiple aggregates at once.


Aggregates are all about transactional consistency. When there is a strong consistency rule between multiple entities, we can deem one of them an aggregate root and make it responsible for maintaining consistency. At the same time, we’re limiting persistence operations to only the root itself, so that it’s not possible to put the aggregate in an inconsistent state by modifying and saving an entity by itself. For best maintainability and scaling, we should strive to update only one aggregate per transaction, keep the aggregates small and make them reference each other only by ID.

For more information about aggregates and DDD in general, I recommend the two great books: DDD by Eric Evans and IDDD by Vaugh Vernon. For a shorter read dedicated to aggregates, one could check out Vernon’s online series about aggregates.

About the Author Grzegorz Ziemoński

King of Tidy Java, nerd that thinks about producing perfect software all the time and proud owner of 2 cats.

follow me on: