Large AggregateMember maps/relationships

Hi All,

I have been playing a bit with modelling an aggregate structure, that from a business domain perspective, would be conveniently modelled as an @AggregateMember Map (with ForwardMatchingInstances).

However, the number of elements in that map would be up to 150,000 quite commonly; as far as I can tell, there is no lazy-loading mechanism for @AggregateMember, so I would incur quite a considerable performance penalties owing to SerDes overheads.

Firstly, am I correct that @AggregateMembers with ForwardMatchingInstances are not lazy-loaded from the event store (Hibernate-style proxy for example)?

Secondly, what are some good patterns in Axon for achieving a similar outcome to the RootAggregate -> Entity pattern?

Any thoughts on this, folks? Wonder if my question is too obtuse, or perhaps just slipped through the cracks.

An example might be something like, an ‘Email’ AggregateMember/Entity belongs to an ‘EmailInbox’ Aggregate; we want to do some deduplication at the inbox level at creation time for the entity (e.g. to reject any ID we’ve seen before), but route subsequent commands directly to the entity – but without loading every other irrelevant email associated with that inbox. Also handy for bulk operations, etc.

Hi Marc,

in Axon, aggregates are loaded into memory entirely. In some cases, when using state-stored aggregates, you may be able to benefit from lazy-loading, but once you publish an event, Axon will need to iterate over the collections to publish the event to the entities. In an Event Sourced aggregate, this is not even an option.

Do note that your command model does not need to reflect the “entity model” as one would expect it in a traditional architectural style. So in your email /inbox example, do you need to keep track of all emails to simply be able to validate actions? Or even better, does your system relly have an invariant that requires all emails in an inbox to be fully consistent?

Note that the “deduplication of ID” is a set-validation problem. There are several ways to address this problem, one of which is to keep a “table” with all claimed IDs in there. In training sessions, I always emphasize that the command model is more than only aggregates.

There is a nice writeup of different options here: https://danielwhittaker.me/2017/10/09/handle-set-based-consistency-validation-cqrs/

Cheers,

Hey Marc,

we’ve resolved our huge relationships to linked @Aggregates managing their relationships (your option 1) and are quite satisfied with that. Our main reason to do so was to keep the number of events per aggregate instance as low as possible for performance reasons - so now we’ve sliced our domain such that our aggregate instances have some 100 events over their lifetime in total.

The biggest challenge for us was to keep the command model consistent when creating entities and executing cascade operations. We have a 4-layered hierarchy in our domain model, each entity is modeled as separate aggregate managing the relationship with it’s parent by storing the id of the parent:
Auto Generated Inline Image 1.png

We solved creating by running the create command of a child via the parent aggregate (to validate the parent exists) but from there only sending a create command to the child aggregate without having any event published in the parent - so we can be sure the parent exists during creation.
For cascading operations (e.g. deleting a tree starting from a parent) we keep a command model that reflects the relationships (a flat domainEntity table having ids and parentIds) and iterate it to cascade commands down through the entity tree.

You can also find a discussion on cascade operations here: https://groups.google.com/g/axonframework/c/860POX06EiQ

Best Regards,
Jakob