In an event-driven microservice architecture, services typically need to update their domain state and publish an integration event on a service bus at the same time (both operations are complete or none). When using a relational database, this is usually done with the help of the send box template: only one entry is saved in the database, which indicates that the event X must be published. This entry is saved as part of the same transaction that contains the domain status changes. A background process then queries these entries and publishes the events. This means that the event will eventually be published, which will make the system consistent.
However, NoSQL databases do not support the idea of updating multiple documents in a single transaction, and many of them do not support it without great solutions. You will find below a list of potential solutions (some more ugly than others):
1. Variation of the model of the shipping box:
Send box template, but instead of having a separate collection of documents for pending events, they will be saved as part of the domain entity. Each domain entity will encapsulate a collection of events that remain to be published and a background process will query these entities and publish the events.
- If the background process publishes the event but fails to delete it
from the domain entity, it will republish it. This should not really be a problem if the updates are idempotent or if the event manager is able to identify duplicate events.
- Domain entities are
corrupted with integration events.
2. Event search:
Event search eliminates this problem, but it is very complex to implement and represents a significant cost for small microservices.
- Complex, may require a complete overhaul of how services work with data.
3. Listen to your own events:
The service will only publish an event to which it is also subscribed (it will not update its status as part of the same operation). When the service bus returns the event for processing, the service updates its domain entity.
- Other microservices can handle the event before the microservice of origin. This can cause problems if they assume that the event has already occurred while it is not.
Are there other solutions to this problem? What is the best?