Choose correct AggregateIdentifier

Hello everyone,

me an my team are currently in the situation to start a new project/product and want to evaluate whether Axon Framework (or Event Sourcing in general) is a fit for our type of application.

Brief Intro: We are building a custom loyalty application for a bigger eShop. Users can enroll to our loyalty program and will be rewarded for making orders etc. Our eShop is divided into several verticals and our team is only responsible for the loyalty part. This results in the fact that we consume lots of data and events produced by other systems/verticals

Question: The general eShop account of a customer is handled by another team. Each user has a unique identifier (lets call it “accountId”) that is known and used by all other systems as well to identify a customer account. We also introduced an aggregate CustomerAccount in our system with the AggregateIdentifier “accountId”. The CustomerAccount aggregates get created by replicating + mapping the events from the team that owns the Customer Accounts.
Now we would like to have an additional Aggregate “Enrollment” that gets created when an customers enrolls to our loyalty program. The problem is what should be the AggregateIdentifier of that Aggregate? It would be tempting to use the “accountId” as well for the Enrollment-Aggregate, because each incoming event from other systems (orders, order-cancellations, email-subscriptions …) could be naturally associated to an enrollment. On the other hand, the enrollment has a different life-cycle then the CustomerAccount, because Users could opt-out and later enroll again to our loyalty system, so deletion (markAsDeleted) for our Enrollment-Aggregates would not be possible when we use the “accountId” as AggregateIdentifier.
The other option is to use a random UUID as AggregateIdentifier for enrollments. But then we would need some kind of MappingTable on the command-side of our application to map each incoming event to an enrollment . So my question is, what is generally recommended in this situation? Is there some kind of pattern for the former option (mapping-table on the command-side) or some kind of support in the axon framework?

Sorry for the long text :slight_smile:

Best regards,
Julian

Hi Julian,

identifiers are always tricky, especially in event sourced systems. The solution in general, is quite simple: always use technical identifiers such as UUIDs. And yes, that does mean that somehow, you will need to be able to map what’s coming in to this technical identifier. When using UI’s, or other APIs where components retrieve a list of items first, you can return this technical ID as part of it. If interaction is more “imperative” and doesn’t have any queries first, then you would have to map the incoming information to a technical ID.

The fact that you indicate that a single User to enrol more than once is a good indicator that you can’t use the UserID as the enrollment identifier. There, you would perform a query to find any active enrollment for a given UserID. If there is none, you create a new enrollment. If there is, you either need to cancel that one and create a new one, or perform an action against that existing enrollment.