Domain events, representing something that has happened in a domain, were not defined as a Domain-Driven Design (DDD) pattern when Eric Evan's original DDD book was released but are now a tactical element in DDD and a full member of domain models. Eventual consistency is a design approach for improving scalability and performance and domain events can help in achieving this by acting as a trigger carrying domain information, Florin Preda explains in a recent blog post.
In a transactional consistency workflow, familiar to most developers, a client executes a command on a system which then runs all operations required to maintain the domain consistency inside a transaction. When the client gets the response either all operations have succeeded or all have failed, there is no middle ground.
In an eventual consistency workflow, common in distributed systems, a client executes a command on a system but only a part of all operations required to maintain the domain consistency is run inside a transaction. The rest of the operations are run at a later time, after which time the system will be consistent.
Preda notes that although transactional consistency seems more straightforward and easier to use, there are scenarios where he thinks eventual consistency has an advantage. Using two operations, A followed by B, as an example he describes four such scenarios:
- Operation B takes a long time to execute.
- Operation B is asynchronous by nature, i.e. depends on an asynchronous mechanism.
- Operation B is performed against a different aggregate than Operation A but within the same bounded context.
- Operation B is performed inside a different bounded context than Operation A.
Scenarios 3 and 4 are for Preda related to Domain-Driven Design (DDD) and for these two he believes that choosing eventual consistency will lead to a better design compared to working with traditional transactions. This is where domain events can be helpful. They are a representation of something that happened in a domain that is relevant to a domain expert and facilitate eventual consistency by acting as triggers starting the next step in a workflow and carrying the domain information needed.
Writing about the same subject Mike Mogosanu claims that in real world use cases transactional consistency workflows are rare; a business process often involves a series of use cases and persisting a group of changes using the Unit of Work (UoW) pattern is then a naive solution complicating things from a technical point of view, especially when working in distributed applications.
Mogosanu believes that a business process involving different bounded contexts should be considered being eventually consistent with at least one domain use case per bounded context. Domain use cases are responsible for keeping aggregates consistent, and here the UoW pattern is usable, and for publishing domain events that trigger start of other use cases, eventually bringing the whole system to a consistent state.
Exemplifying his ideas Preda uses a simplified version of a design from Vaughn Vernon’s book Implementing Domain-Driven Design in an implementation of an application in C# using Azure Service Bus messaging system for transport of events.