So I have some actual experience with Event-driven architecture myself but this week I followed an interesting webinar from ThoughtWorks about this specific topic. Here are my main takeaways.
It is nothing new
Events are nothing new. Events are everywhere and life itself is actually just a set of events.
It is valuable to the business
It is a really natural way to describe your business. For example, a customer adds an item, drops an item, and adds again a new item to their basket. Having these events stored, gives great insight into a customers behaviour.
It adds structure to the system
Events are a functional way to design workflows with immutable events. They provided a mechanism to easily extend other workflows in a loosely coupled way. Events also let you focus on what valuable information your domain has and what information is relevant for other domains.
A great example of event-sourcing is Git. Instead of storing the latest state, Git stores events that contain what changed. You can easily go back to a previous state or browse through all the changes that happened over time.
Event orchestration is when you have a single service that is telling the other services what to do and when to do it. This is like the conductor in an orchestra who shows the musicians what to do.
Event choreography on the other hand is more decentralized. The services communicate with each other and know what they have to do in relation to the other. This does not require supervision and instructions.
Event streaming is taking it to the next level where you have real-time event streams and processes, and smaller systems to do other things like filtering streams, produce new streams, etc. What an event stream actually is, was not really clear after the webinar. But after doing some research I found out that an event stream has to do with persisting events and can be used to get a view of the events. For example, one can have two event streams, one which contains every change made in chronological order and one which provides the latest view of an entity.
Challenges of an Event-Driven Architecture
Every architecture has challenges and working with events requires a little bit of a different mindset.
Things will go wrong. Let’s say you store something in a database and then publish an event. Either of these processes can fail. What can we do in this case? Did subscribers already process our event? And what to do with missing events?
The first question you should ask yourself is, is it okay to miss the event or is it crucial and do we put in the extra work?
One pattern you can use is the outbox pattern. In this pattern you store transactions in the database and in a separate process you read from the database, scan for updates, and publish events in a reliable way to a broker.
Some frameworks also offer this out of the box. So service A publishes an event and service B is offline. When service B comes back online, it starts reading events from where it stopped.
Observability and debugging
In a complex system, it is crucial to be able to debug the system and have a way to see what’s happening inside. The developers from Thoughtworks came with a few options.
- Have correlation ids on all events.
- Have standardized log formats.
- Have a good tool for searching logs with a correlation id.
Business changes often and our software as well. Here are a few things to consider.
- Have contracts in place. Contracts say what an event looks like.
- Have good communication between teams, so that you know when things change.
- Communicate with all the consumers about the change of the event update.
- To avoid breaking or having to update other systems, you can also decide to publish using another schema.
Slicing the work
Generally, we want stories to center around the business value that they add. Because events often require changes in many different services, we could end up with monster user stories.
To avoid this we can slice the work in smaller parts and still keep the ability to show progress to the stakeholders. We can for example publish to the event broker without having the consumers. This gives us the opportunity to share progress and show what the change would be. The next step will be to actually build the consumers.
Event-driven architecture can be a useful tool to refactor legacy systems. Focus on getting the data out of the legacy system. You can do this by reading from the database and publishing events into a new event stream to integrate with the old system.
Commands tell us that we have to do something. Often people use passive-aggressive events. An example: the teapot is empty. Some subscriber picks up this event and fills the pot. What you actually want to say is: fill up the pot.
Events are just notifications, letting the consumers know something has happened. No one needs to do anything about it. You can do something about it, but I could just be shouting into the wind.
When we are talking more about the state, this is the state and this has to happen, then we are looking more at commands. By using passive-aggressive events we are losing the choreography of events.
When deciding if you are going to use techniques like CQRS or Event-sourcing, you do not have to follow them to the letter. It is ok to just pick what you need and what works for you and just drop the parts that are not useful.
It was an interesting webinar, where I learned some new terms and techniques that can start my further research into some topics related to Event-driven architecture. For example, having the right names for event orchestration, choreography, etc is really steering me in the right direction.