Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Should a single command address multiple aggregates?

In CQRS and DDD, an aggregate is a transactional boundary. Hence I have been modeling commands always in such a way that each command always only ever addresses a single aggregate. Of course, technically, it would be possible to write a command handler that addresses multiple aggregates, but that would not be within a single transaction and hence would not be consistent.

If you actually have to address multiple aggregates, I usually go with a process manager, but this sometimes feels like pretty much overhead. In addition, from my understanding a process manager always only reacts to domain events, it is not directly addressed by commands. So you need to decide which aggregate to put the starting point to.

I have seen that some people solve this using so-called domain or application services, which can receive commands as well, and then work on multiple aggregates – but in this case the transactional nature of the process gets lost.

To give a simple example, to better illustrate the scenario:

  • A user shall join a group.
  • A user has a max number of groups.
  • A group has a max number of users.

Where to put the command that triggers the initial joining process, and what to call it? user.join(group) feels as right or wrong as group.welcome(user). I'd probably go for the first one, because this is closer to the ubiquitous language, but anyway…

If I had something above the aggregates, like the aforementioned services, then I could run something such as:

userManagement.addUserToGroup(user, group);

However, this addUserToGroup function would then need to call both commands, which in turn means it has to take care of both commands being processed – which is somewhat counterintuitive to having separate aggregates at all, and having aggregates as transactional boundaries.

What would be the correct way to model this?

like image 554
Golo Roden Avatar asked Nov 01 '25 22:11

Golo Roden


1 Answers

It may be worth reviewing Greg Young on Eventual Consistency and Set Validation.

What is the business impact of having a failure

This is the key question we need to ask and it will drive our solution in how to handle this issue as we have many choices of varying degrees of difficulty.

And certainly Pat Helland on Memories, Guesses, and Apologies.

Short version: the two generals tell us that, if two pieces of information must be consistent, then we need to write both pieces of information in the same place. The "invariant" constrains our data model.

The invariant you describe is effectively a couple of set validation problems: the "membership" collection allows only so many members with user A, and only so many members with group B. And if you really are in a "we go out of business if those rules are violated" situation, then you cannot distribute the members of that set -- you have to lock the entire set when you modify it to ensure that the rule is not broken and that first writer wins.

An element that requires some care in your modeling: is the domain model the authority for membership? or is the "real world" responsible for membership and the domain model is just caching that information for later use? You want to be very careful about trying to enforce an invariant on the real world.

There's a risk that you end up over constraining the order in which information is accepted by the model.

like image 131
VoiceOfUnreason Avatar answered Nov 04 '25 20:11

VoiceOfUnreason



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!