In an event-driven microservices architecture, services typically need to update their domain state while publishing an integration event on a service bus (either completed or not completed). When using a relational database, this is usually accomplished by using the Outbox pattern: the database stores a single entry indicating that Event X needs to be published. This entry is saved as part of the same transaction that contains the domain state changes. A background process queries these entries and publishes the events. This means the event will eventually be published, eventually making 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 this without ugly workarounds. Below is a list of possible solutions (some uglier than others):
1. Deviation of the postal issue pattern:
Outbox patterns, but instead of having a separate collection of pending event documents, are stored as part of the domain entity. Each domain entity encapsulates a collection of events that still need to be published, and a background process queries those entities and publishes the events.
- If the background process publishes the event, but does not remove it
It is republished by the domain entity. This should not actually be a problem if updates are not essential or the event handler can identify duplicate events.
- Domain entities are
damaged by integration events.
2. Event Sourcing:
Event sourcing addresses this problem, but is very complex to implement and requires a lot of effort for small microservices.
- Complex, it may be necessary to completely revise the way services work with data.
3. Listen to your own events:
The service publishes only one event that is also subscribed (it does not update its status as part of the same operation). When the service bus returns the event for treatment, the service updates its domain entity.
- Other microservices can handle the event before the original microservice. This can lead to problems if it is assumed that the event has already occurred, although this is not the case.
Are there any other solutions to this problem? Which is the best?