Message Bus vs Mediator Pattern vs In-Memory Bus

domain-driven-designmessage-queuemicroservices

I am struggling to understand when to use each of these:

1) Message Bus: Used to send integration events between Microservices. For example, Microservice A could publish an integration event, which is handled by Microservice B and Microservice C. The benefit of a Message Bus e.g. RabbitMQ is that it could be durable meaning if one of the Microservices is down then it can handle the event later. It also guarantees delivery.

2) Mediatr (Mediator pattern): Using CQRS the Mediatr pattern can be used to decouple commands and events making the MVC controller/service thinner.

I see how both of these patterns can be used in the same environment. I then see code like this:

3) In Memory Bus: https://github.com/gregoryyoung/m-r/blob/master/SimpleCQRS/FakeBus.cs. It is an In Memory bus.

What is the difference between using Mediatr and an In Memory Bus? The way I am thinking at the moment is that Mediatr is more appropriate when using the Observer pattern and an In Memory Bus is more suitable when using the publisher/subsciber pattern. Have I understood this correctly?

Is it appropriate to use an InMemory Bus for a single Microservice (for domain events) and a durable Message bus for integration events (between Microsservices)?

Best Answer

A mediator pattern creates a flexible decoupled interface between two microservices. Messages are sent to and from each microservice without one necessarily having to know all the explicit workings of the other.

This pattern is ideal if you think the relationship between the two might change significantly in the future. The mediator could be standalone and it could persist messages in case of failed delivery, so potentially it can be just as stabile as the message bus.

A publish-subscribe pattern which is basically your message bus, isn't just for two interfaces. It is potentially for multiple interfaces, allowing for maximum flexibility. The flexibility also extends to the message itself, meaning the message must be easily sent and received by anyone interested in receiving said message when an event occurs. This also implies you may have problems down the road with versioning if you're not careful, as changes in messages being passed must be consistently interpreted across microservices, unlike the mediator. When the message changes, then only the mediator absolutely must also be updated for everything to work properly.

An in-memory bus isn't really a pattern so much as a message bus with no persistence. It is faster, but also not ideal when there are unexpected failures, as you don't know where the error occurred and would have serious difficulty trying to restore the previous situation. In any production context, I wouldn't recommend this, even if it wrote to a log file.

I hope that answers your question!

Related Topic