domain-driven-designdddd

Domain Events for syncing data to other microservices


I am trying to learn more about DDD and was going through the DomainEvents. Let's say we have three microservices Service A, Service B and Service C.

Service A has an entity Foo defined as below:

public class Foo : AggregateRoot
{
    public string id {get; private set;}

    public string name {get; private set;}

    public string email {get; private set;}
}

and the Service B is a service that depends upon the email from Foo while the Service C depends on the name from Foo and the data is replicated from Service A to Service B and to Service C whenever there is a change in the values of Foo via a Bus.

Guidelines about Domain Events that I came accross:

  1. Do not share excess information as part of the DomainEvent data.
  2. When consuming BoundedContext knows about Producing BoundedContext maybe share the Id otherwise share full information
  3. Don't use DomainClasses to represent data in Events
  4. Use Primitive types for data in Events

Now the question that arose due to conflicting guidelines:

Does it mean that I should fire two different events when they change like FooNameChange and FooEmailChanged and only use the id along with the updated value as part of the Event Payload?

Or can I just make a single DomainEvent called FooChanged and take the state of the Foo serialize it and fire the event. Then write up a handler as part of the same BoundedContext that would take the data and drop it on the Bus for any service subscribed to the message and the individual service decides on what actions to take based on the Id that was attached and the event arg (the updated data).


Solution

  • If you need to talk across services, you should be perhaps looking for Integration Events instead of "Domain Events" From Microsoft Docs

    Domain events versus integration events

    Semantically, domain and integration events are the same thing: notifications about something that just happened. However, their implementation must be different. Domain events are just messages pushed to a domain event dispatcher, which could be implemented as an in-memory mediator based on an IoC container or any other method.

    On the other hand, the purpose of integration events is to propagate committed transactions and updates to additional subsystems, whether they are other microservices, Bounded Contexts or even external applications. Hence, they should occur only if the entity is successfully persisted, otherwise it's as if the entire operation never happened.

    As mentioned before, integration events must be based on asynchronous communication between multiple microservices (other Bounded Contexts) or even external systems/applications.

    Thus, the event bus interface needs some infrastructure that allows inter-process and distributed communication between potentially remote services. It can be based on a commercial service bus, queues, a shared database used as a mailbox, or any other distributed and ideally push based messaging system.

    What information you send within the integration events, it really depends. You have the following choices: