Route one command to multiple aggregates

hello,
we are looking into a problem that one command needs to be handled by multiple aggregates, is it possible to have it using RoutingStrategy, or even another good practice?
our use case:

  • we calculate the salary for employees based on multiple criteria: worked hours - vacations - bonus…etc, and we have a field of the aggregate which is the hourly wage. so we designed our aggregates such that we have one aggregate per employee per month. and when this hourly wage gets changed, we need to fire one command that handled by all salary aggregates to update the state, salary…etc.
  • the problem is that we don’t have a list of all salary aggregates ids per driver so that we can loop on them and fire the command, so we was thinking to have some sort of routing strategy that takes one command and forward it to multiple salary aggregates, is this possible?

Hi Karim,

it is impossible to route a command to multiple locations. That’s by design, because it’s conceptually impossible (when using event sourcing) to have a single operation to update a batch of entities.
If you have batch operations, you essentially have a single command handler that then dispatches individual commands to each of the aggregates that you wish to modify. Most likely, you’ll need to do a query to find the maching aggregates and then send individual commands.
To me, it sounds like you’ll have to build that projection to be able to find the “salaryId per driver”. The good news about event sourcing is that it shouldn’t be too hard.

Hope this helps you with your challenge at hand.
Cheers,

Allard Buijze

CTO

hi Allard,
Thanks a lot that makes a total sense. But is it a good practise to have such projection in the “command service” that only serve the purpose of this use case?
we was thinking also to have a saga that collects those IDs per user in its internal state. and forward the commands to those, but I am not sure what would be the better practise here. What would you advise?

Hello Karim,

whether a Saga or a projection is the better approach really depends on your use case. However, in general, if you have two options, of which one is the Saga, then pick the other one ;-).
In this case, the “intended audience” of the projection is a command handling component. Yes, I would highly recommend keeping it close to that component. You may even consider not using the Query Bus for this, as you typically don’t want/need “location transparency” for this query. You want the data to be locally available.

Cheers,

Personally, I like to use this command side projections to solve similar problems. This can be valuable in situations when you can not make a decision in the command handler based on the state of the event-sourced aggregate only, for example, uniques (we have to guarantee that all User aggregates have unique Name/Email). As Allard stressed already, you should keep this small projection within the command component/module. This projection should not expose any Query API outside of this component, it should be used only inside the command component/module to make the right decision in your aggregate(s). Additionally, you can choose to use Subscribing Event Processors to materialize this small projection. Subscribing Event Processors are invoked by the thread managed by the publishing mechanism (in the same transaction) and they will keep your projection immediately consistent with the state of your aggregate(s).

This way your command side (your business logic) owns this projection data.
Please do not misuse this :), you should try to make decisions in your command handlers based on the aggregate state only, and use this command side projections as a last resort.

Best,
Ivan