Sponsor: Do you build complex software systems? See how NServiceBus makes it easier to design, build, and manage software systems that use message queues to achieve loose coupling. Get started for free.
Event Driven Architecture has many benefits. Loose and temporal coupling, scaling, resilience, and more. But what does that mean? What are some actual use-cases? I’m going to describe 4 practical examples of real-world event driven architecture.
Check out my YouTube channel where I post all kinds of content that accompanies my posts including this video showing everything that is in this post.
The first practical use-case for real-world event driven architecture is integrating with external 3rd party services. In a lot of systems, when something occurs (an event) you need to interact and exchange data with a 3rd party service. This is where Event Driven Architecture can really shine.
As an example, let’s say we have a Sales boundary that when an order is placed we need to send the customer an order confirmation email, send them a text message (SMS), and possibly also have a Webhooks system to make calls to other HTTP APIs.
The beauty of event driven architecture is that each one of these concerns (email, SMS, webhooks) is decoupled from the action of placing an order. Each consumer has their own responsibility for handling each concern.
One consumer is responsible for generating an email and sending it to AWS Simple Email Service (SES).
Another consumer, concurrently but in complete isolation can be responsible for making HTTP calls to external systems in the form of webhooks.
Lastly, there could be another consumer responsible for sending a text message (SMS) to Twilio.
Each one of these consumers is independent of each other as well as the initial publisher (Sales) of when an order was placed. Each is executed independently without interference from the other.
Since you don’t own external services, it’s hard to guarantee any type of availability. This means if one consumer is having availability issues downstream (AWS SES, Twilio, etc) all other consumers responsible for different external integrations are completely unaffected.
This allows you to integrate all different ways in a plug-in-play fashion. Need to add some new functionality? Add a new consumer.
Long-running business processes and workflows can be difficult to manage. Event Driven Architecture allows many different logical boundaries that perform specific behaviors apart of a long-running business process.
Let’s say the Sales boundary publishes an Order Placed event.
Our Billing service needs to know when this occurs so that it can Bill the customer or create an invoice.
Once the order has been billed, we then want to allocate the product in the Warehouse and create a shipping label. For this to happen the Billing service will publish an Order Billed event.
The Warehouse will consume that Order Billed event to then allocate the product and create a shipping label.
The last portion of this workflow now is for Sales to know when the Shipping Label has been created by the warehouse, so it can update the Order Status from “Order Placed” to “Order Ready to Ship”.
There are different ways to achieve this, but specifically outlined above is called Event Choreography. You can also manage this workflow with Orchestration.
Each service is responsible for a portion of the workflow, without realizing they are. The Billing service doesn’t care about a shipping label being created within the Warehouse. All it cares about is when an Order Placed event occurs from Sales, it needs to Bill the customer and publish an Order Billed event.
Each service boundary is doing its part in this long-running business process.
Changing the shape of data for different use cases can be really helpful as an example of real-world event driven architecture.
We can leverage Event Driven Architecture to tell consumers when data has changed so they can update their copy of the data.
Let’s say we have three different types of data stores. One is a cache, another is a data warehouse we use for Reporting and BI, and the other is a data lake we dump data to for future use.
In order to keep all these data stores updated, we can publish an event that contains the data that changed.
From there we can have various consumers that take the event and mutate the data in their respective data stores. We may have a cache that needs to be invalidated as well as a data warehouse that needs to be updated.
Also independently we can have a consumer that dumps that in a data lake for future use.
What this allows you to do is be more real-time about various read models that your system uses. You likely won’t always have a single type of database as a system grows and has different needs and requirements. A common example is OLAP for reporting and OLTP for business processes.
Lastly, removing temporal coupling between your own internal systems is a major benefit to Event Driven Architecture.
When making synchronous blocking request-response calls between services, we’re adding temporal coupling. When an order is placed in the system, if we’re using HTTP calls or gRPC to call between services, we’re temporally coupled. This means that all the services need to be available at the same time in order for everything to be functioning correctly.
In the example above, Sales needs to call Billing to charge the customer when an order is being placed.
After that is done, it then has to make another blocking synchronous call to the Warehouse. But what happens if that call fails or the Warehouse service is unavailable? We’ve already charged the customer in the previous call to the Billing service. We have no distributed transaction so there is no rollback.
This is why in the example earlier I illustrated the workflow using a message broker because we remove the temporal coupling. Each service operates independently without being constrained by the availability of other services.
When an order is placed, if the Billing service is unavailable, nothing fails. When it comes back online and picks up the Order Placed event from the broker, it will continue the workflow.
Once you remove temporal coupling, you start treating your internal services, just like the external services I was mentioning at the very beginning. When you move to an event driven architecture because everything is independent, it doesn’t require everything to be online and available to complete long-running business processes and workflows.
Real-World Event Driven Architecture
Hopefully, this illustrated the different ways you can leverage an event driven architecture. Integrating with 3rd party external services, handling long-running business processes and workflows, changing the shape of data in real-time for analytics and reporting, and removing temporal coupling to add resilience.
Developer-level members of my YouTube channel or Patreon get access to a private Discord server to chat with other developers about Software Architecture and Design. As well as access to source code for any working demo application that I post on my blog or YouTube. Check out the YouTube Membership or Patreon for more info.