Microservice Geeks
Published in

Microservice Geeks

Introduction to Event-Driven Architecture

The essential concepts that every developer should know

A Simple Definition

The Event That Never Happened

{
"orderId": "760b5301-295f-4fec-95f8-6b303a3b824a",
"customerId": 28623823,
"productId": 31334,
"quantity": 1,
"timestamp": "2021-02-09T11:12:17+0000"
}

Channelling Events

Event-Driven Architecture Reference Model
  • Events are actions of interest that occur at discrete points in time and may be externally observed and described.
  • Events are persisted as records. Events and records, despite being related, are technically different things. An event is an occurrence of something (e.g., a state change), and is intangible on its own. A record is an accurate description of that event. We often use the term event to refer to its record.
  • Producers are receptors that detect events by publishing corresponding records to a stream.
  • Streams are persistent sequences of records. They are typically backed by one or more disk-based logs under the hood. Equally, streams might be backed by database tables, a distributed consensus protocol, or even a blockchain-style decentralised ledger.
  • Brokers govern access to streams, facilitate the reading and writing operations, handle consumer state and perform various housekeeping tasks on the streams. For example, a broker might truncate the contents of a stream when it overflows with records.
  • Consumers read from streams and react to the receipt of records. A reaction to an event might entail some side-effect; for example, a consumer might persist an entry into its local database — reconstructing the state of a remote entity from its published “update” events.
  • Consumers and producers may overlap; for example, where the reaction to an event might be the production of one or more derived events.

Decoupling Through Asynchrony & Generality

Conceptual model of coupling
  1. Recall, events are not communicated, they just occur. The component raising an event (by publishing a record) has no awareness of other components that may or may not exist. Therefore, the producer will not cease working if the consumers are unavailable — provided that the broker can durably buffer the events without imposing back-pressure upon the producer.
  2. The persistence of event records on the broker largely eliminates the notion of time. A producer may publish an event at time T1, while a consumer may read it at T2, with T1 and T2 potentially being separated by milliseconds (if all is well) or hours (if some consumers are down or struggling).

Styles of Event Processing

Discrete event processing

Event stream processing

Complex event processing

When to use EDA

  1. Opaque consumer ecosystem. Cases where producers are generally unaware of consumers. The latter might even be ephemeral processes that could come and go with short notice!
  2. High fan-out. Scenarios where one event might be processed by multiple, diverse consumers.
  3. Complex pattern matching. Where events might be strung together to infer more complex events.
  4. Command-query responsibility segregation. CQRS is a pattern that separates read and update operations for a data store. Implementing CQRS can improve the scalability and resilience of applications, with some consistency trade-offs. This pattern is commonly associated with EDA.

Benefits of EDA

  1. Buffering and fault-tolerance. Events might be consumed at a different rate to their production and producers mustn’t slow down for the consumers to catch up.
  2. Decoupling of producers and consumers, avoiding unwieldy point-to-point integrations. It’s easy to add new producers and consumers to the system. It’s also easy to change the implementations of producers and consumers, provided that the contracts/schemas constraining the event records are honoured.
  3. Massive scalability. It is often possible to partition event streams into unrelated substreams and process these in parallel. We can also scale the number of consumers to meet the load demands if the backlog of events grows. Platforms like Kafka enable the processing of events in strict order while simultaneously allowing massive parallelism across the stream.

Drawbacks of EDA

  1. Limited to asynchronous processing. While EDA is a powerful pattern for decoupling systems, its application is limited to the asynchronous processing of events. EDA does not work well as a substitute for request-response interactions, where the initiator must wait for a response before continuing.
  2. Introduces additional complexity. Where traditional client-server and request-response style of computing involves just two parties, the adoption of EDA requires a third — a broker to mediate the interactions between producers and consumers.
  3. Failure masking. This is a peculiar one as it seems to run contrary to the grain of decoupling systems. When systems are tightly coupled, an error in one system tends to propagate quickly and is brought to the forefront of our attention, often in painful ways. In most cases, this is something we would like to avoid: the failure of one component should have as little effect as possible on the others. The flip side of failure masking is that it inadvertently conceals problems that should otherwise be brought to our attention. This is solved by adding real-time monitoring and logging to each event-driven component, but this comes with added complexity.
Benefits and drawbacks of event-driven architecture

Things to watch out for

  1. Convoluted choreography. With loosely coupled components, one can get into a situation where the architecture might resemble a Rube Goldburg machine, whereby the entire business logic is implemented as a series of side-effects that are disguised as events: one component might raise an event that triggers a response in another component that raises another event, triggers another component, and so forth. This style of interaction between components can quickly become difficult to understand and reason about.
  2. Disguising commands as events. An event is a pure depiction of something that has happened; it does not prescribe how the event should be handled. On the other hand, a command is a direct instruction addressed to a specific component. Because both commands and events are messages of sorts, it is easy to get carried away and misrepresent a command as an event.
  3. Remaining agnostic of consumers. Events should capture relevant attributes in a way that does not limit how those events may be processed. This is easier said than done. Sometimes we might be privy to more information that could, in theory, be added to an event record, but it’s not clear whether adding that information to the record is useful or if it just leads to useless bloat.

Conclusion

--

--

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store