Domain Events for syncing data to other microservices

853 Views Asked by At

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).

2

There are 2 best solutions below

0
On BEST ANSWER

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:

  • Publish the event such as FooNameChanged, FooEmailChanged with only Id of Foo. In that scenario, if your consumers need further information of what has changed, they would need to make a call your service (perhaps a REST API call). A disadvantage of this approach is that if you have many subscribers to your event then all those services would call your service to get the details of the event almost at the same time.

  • Publish the event with the full data (note that it is not same as your Domain) which a consuming service may need such as PerviousValue, CurrentValue, etc. If your payload is not huge, this can be a good option. These types of events are typically called "FAT events"

0
On

DomainEvents are not patch documents.

Which is to say, we aren't trying to create general purpose descriptions of changes, but instead to align our messages with the concepts of our domain as we understand them.

So whether two changes belong in the same event, or in different events, gets a big "it depends".