Event Sourcing + Updates to multiple aggregates

concurrencyevent-sourcing

I'm trying to learn about event sourcing for potential application to a booking system I am building – I think I understand the core concepts, but I'm having trouble understanding how to handle cases where updates to multiple aggregates / streams are required.

In my case I have modeled two aggregates – Events, which track the number of available seats, and Bookings for one or more seats at a single event which record details about the attendees. Everything I have read indicates that a transaction should update only a single aggregate, however when saving a Booking I need to update both the Event to track the remaining seats at the event, and the Booking to record changes to the attendee details. This creates the potential for inconsistency:

  • If I update the Booking before the event I need to handle the case where the update to the Event fails because the seats are no longer available (this happens even if I add a "Reserve your seats for the next 10 minutes" step, because at some point I need to update the booking details and confirm the seats).
  • Conversely if I update the Event first I need to handle cases where someone has managed to concurrently modify the Booking and there is a conflict.
  • In both cases an unexpected error will leave the Booking and Event inconsistent and I'm unsure how I could handle this.

I've tried looking into how similar problems in other domains are handled (e.g. transferring money between accounts), but I'm not 100% clear as to how those strategies ensure "eventual consistency", and so I'm not really sure how to apply this in my case.

How should updates to multiple linked aggregates be handled?

Best Answer

How should updates to multiple linked aggregates be handled?

Updates to multiple aggregates should each be applied in separate transactions. If this results in an unacceptable situation for the business, then the conflict should be detected and invoke the remediation policy.

It is often the case that over booking is allowed by the business (in cargo shipping examples, you will often see that there is a deliberate policy in place for booking beyond capacity).

In this case, that would probably mean that you change the bookings in an transactionally consistent way. The process manager, listing to the booking events, would then command the event to update. The event aggregate would accept the increased number of reserved seats, and fire two events - one announcing its current count of seats, and another announcing that the capacity of the event had been exceeded. Another process manager listens for the capacity exceeded event, and starts the mitigation process.

On the other hand, if the business invariant really is an absolute - if the business really can't allow more bookings than there is space at the event - if eventual consistency isn't good enough, then you have to accept the fact that you've got a business invariant that requires data from two different entities, and you need to find a model that incorporates those entities into the same aggregate.

Related Topic