Domain-Driven Design – Domain Events vs Application Events

aggregatedomain-driven-designeventual-consistencymicroservices

I'm considering two types of notifications:

  • Domain events used internally within a bounded context
  • Application events used to exchange notification messages between bounded contexts

Each aggregate in my bounded context defines its own transactional boundary, so that only one aggregate is modified per transaction. When a transaction is successfully committed, a domain event is published asynchronously and internally in order to inform the other aggregates of the bounded context that something happened.

A few application services in the bounded context react to these events. They each update an aggregate in a separate transaction. At the end, all the aggregates of the bounded context are made eventually consistent.

I need to publish some of these domain events to other bounded contexts. But I would feel more comfortable if I could keep a loose coupling between the domain events of each bounded context and the notification messages that are exchanged between the bounded contexts. Furthermore, I can foresee situations where there is not always a 1-1 match between domain events and application events, rhetorically speaking.

Then I have some questions:

  • Is this a correct usage of domain events within a bounded context?
  • If the container / VM that hosts the bounded context (implemented in a micro-service) crashes before all the aggregates are made eventually consistent, I have an inconsistent state when the micro-service is restarted. In his red book, Vaughn Vernon suggests the implementation of an event store. There are several advantages to having an event store, but among all these advantages, will it help solving the inconsistency issue?
  • Shall I really separate domain events from application events?
  • If I do implement an event store for the domain events, what's the best strategy to turn these domains events into application events and forward these application events to other bounded contexts while making sure that if the delivery of a notification message fails it can be redelivered when needed?

Best Answer

I'm considering two types of notifications

For a number of reasons, the literature is pretty weak here; but I believe that you will find that the taxonomy of "domain events" and "integration events" is more popular than the spelling you are using.

Is this a correct usage of domain events within a bounded context

Pretty much. Many of the earlier uses of domain events had handlers that ran in the same transaction as the triggering "aggregate".

That distinction is important for your other questions -- because the handlers were running in the same transaction, all of the updates would fail or succeed together. That eliminated consistency concerns.

There are several advantages to having an event store, but among all these advantages, will it help solving the inconsistency issue?

No; having an event store won't solve this problem. The main consistency issue that you face is a consequence of the fact that you aren't saving the domain events in the transaction with the aggregate.

If you have the domain events in place, and appropriate plumbing to retry delivery of those events after a restart, then your system can eventually recover itself into a consistent state.

See, for instance, Udi Dahan: Reliable Messaging without Distributed Transactions.