When getting started with Event Driven Architectures, I often hear people confuse Messages and Events (What’s the difference?), but a related misunderstanding is what an event is. This is driven by the change in definition for “Event” in the technology world.
In the olden days when we built Winforms apps, an event was something that a user control sent to the code behind when the user interacted with it. If a user pushed a button, that button generated an event which was sent to the code to be processed. In this type of programming, there were lots of events flying around and event handlers were common. Once an event was handled, it was thrown away by the Winforms architecture.
The definition of an event has changed in Event Driven Architectures, and this old paradigm doesn’t hold up anymore. Now that idea of an event is more closely matched by a message because
- Messages are requests for an action to be performed
- There is an expectation that a message will be handled by some service somewhere
- Messages are temporary, typically being thrown away once processed.
With this in mind, there are some changes to the Winforms Event paradigm that we need to keep in mind when working with messages.
In Winforms eventing, it appeared that the event was sent directly from the event source (the button) to the receiver (the code behind). In actuality there was a bus provided by the Winforms that collected and dispatched the events, but in code one would attach an event handler directly to the object that created the event.
With modern messaging that is no longer the case. The message bus is much more visible now, and must be interacted with exclusively. In fact, in modern messaging we do not know the source of the messages, just their type. The message producer gives the message a predictable type and sends it to the bus, while message handlers register themselves with the bus to receive those message types. This bus can either be an internal bus (think Mediatr) or an external bus (i.e. RabbitMQ).
Note that in this structure the bus has no business logic inside. It does not decide for itself which services receive which messages. Subscribing systems tell the bus what message types they are interested in, and the bus simply delivers those messages as ordered. It is just a holding place for messages until they can be processed.
Some would point out that the bus can represent a single point of failure for an application, and that is true. However, this can be easily managed with standard network architecture approaches, like fail over servers, local persistence, load balancers, etc. In fact, all reputable message busses have support for this built in.
One of the concerns with this type of messaging is that with 1000’s of subscriptions it becomes difficult to follow the path, and that is correct. This is an inherent downside of EDA and there’s nothing that can be done about it.