We tend to design systems based on requests and responses that allow our components to communicate and behave appropriately to streams of information. What do we do when components in our systems are more complex, dynamic, or loosely coupled? Event-driven architecture (EDA) is an architectural style based on an entirely different principle than requests to communicate changes in state, events.
Events are the fundamental entity in EDA that communicate something that has happened. For example, an event can be announced by a button when a user presses it, a mechanism we're familiar taking advantage of in web development with event listeners. Events are pieces of data that describe something that has happened and contain no logic. We call components that emit events event producers or event publishers.
Event producers are components of our system that generate events and announce them to our event-driven framework. Event producers are solely responsible for this and unaware of how we handle the events and where. An event producer's only coupling factor with the components that will react is the event message definition. The event message definition refers to the data and shape of that data that an event includes.
In a request/response-based interaction, two communicating components have a large contract surface area, a measurement of coupling, or how much information components need to know about each other to communicate. For example, we often design components with the expectation of a side effect caused by the processing of a sent request. Additionally, components also must wait for a response. In this model service components and clients are coupled by the contract of what methods are available and logically as requests complete a given function.
Service components in EDA do not behave like a service, and we instead refer to them as consumer components or event consumers. Event consumers, only constrained by the event message definition, react to events. Events are routed to these consumers by an event-driven framework that might be making use of a service we could use a message broker on a worker queue model. Consumers are not constrained to respond to events either, for producers do not expect it. Whenever we can perform a task without any need for the results of the operation, we can consider leveraging an event-driven architecture.
EDA is hard to grasp since we are so used to thinking about software in terms of requests and responses. However, endeavoring to understand it should prove beneficial. Leveraging EDA makes it simpler for us to decouple components, which makes it easy for them to evolve and grow independent of each other. Similarly, EDA allows us to scale horizontally very well since we keep adding more consumers to react to an increasing amount of events.
Cover photo by Artem Beliaikin from Pexels.