What do you mean by “Event-Driven”?
What do you mean by “Event-Driven”?
Martin Fowler
07 February 2017
design
event architectures
Towards the end of last year I attended a workshop with my colleagues in<br>Thoughtworks to discuss the nature of “event-driven” applications. Over the last few<br>years we've been building lots of systems that make a lot of use of events, and<br>they've been often praised, and often damned. Our North American office organized a<br>summit, and Thoughtworks senior developers from all over the world showed up to share<br>ideas.
The biggest outcome of the summit was recognizing that when people talk about<br>“events”, they actually mean some quite different things. So we spent a lot of time<br>trying to tease out what some useful patterns might be. This note is a brief summary<br>of the main ones we identified.
Event Notification
This happens when a system sends event messages to notify other systems of a<br>change in its domain. A key element of event notification is that the source system<br>doesn't really care much about the response. Often it doesn't expect any answer at<br>all, or if there is a response that the source does care about, it's indirect. There<br>would be a marked separation between the logic flow that sends the event and any<br>logic flow that responds to some reaction to that event.
I spoke about this topic in more depth in my opening keynote at goto Chicago in<br>April 2017.
Event notification is nice because it implies a low level of coupling, and is<br>pretty simple to set up. It can become problematic, however, if there really is a<br>logical flow that runs over various event notifications. The problem is that it can<br>be hard to see such a flow as it's not explicit in any program text. Often the only<br>way to figure out this flow is from monitoring a live system. This can make it hard<br>to debug and modify such a flow. The danger is that it's very easy to make nicely<br>decoupled systems with event notification, without realizing that you're losing<br>sight of that larger-scale flow, and thus set yourself up for trouble in future<br>years. The pattern is still very useful, but you have to be careful of the trap.
A simple example of this trap is when an event is used as a passive-aggressive<br>command. This happens when the source system expects the recipient to carry out an<br>action, and ought to use a command message to show that intention, but styles the<br>message as an event instead.
An event need not carry much data on it, often just some id information and a<br>link back to the sender that can be queried for more information. The receiver knows<br>something has changed, may get some minimal information on the nature of the change,<br>but then issues a request back to the sender to decide what to do next.
Event-Carried State Transfer
This pattern shows up when you want to update clients of a system in such a way<br>that they don't need to contact the source system in order to do further work. A<br>customer management system might fire off events whenever a customer changes their<br>details (such as an address) with events that contain details of the data that<br>changed. A recipient can then update it's own copy of customer data with the<br>changes, so that it never needs to talk to the main customer system in order to do<br>its work in the future.
An obvious down-side of this pattern is that there's lots of data schlepped<br>around and lots of copies. But that's less of a problem in an age of abundant<br>storage. What we gain is greater resilience, since the recipient systems can<br>function if the customer system is becomes unavailable. We reduce latency, as<br>there's no remote call required to access customer information. We don't have to<br>worry about load on the customer system to satisfy queries from all the consumer<br>systems. But it does involve more complexity on the receiver, since it has to sort<br>out maintaining all the state, when it's usually easier just to call the sender for<br>more information when needed.
Event-Sourcing
The core idea of event sourcing is that whenever we<br>make a change to the state of a system, we record that state change as an event, and<br>we can confidently rebuild the system state by reprocessing the events at any time<br>in the future. The event store becomes the principal source of truth, and the system<br>state is purely derived from it. For programmers, the best example of this is a<br>version-control system. The log of all the commits is the event store and the<br>working copy of the source tree is the system state.
Event-sourcing introduces a lot of issues, which I won't go into here, but I do<br>want to highlight some common misconceptions. There's no need for event processing<br>to be asynchronous, consider the case of updating a local git repository - that's<br>entirely a synchronous operation, as is updating a centralized version-control<br>system like subversion. Certainly having all these commits allows you to do all<br>sorts of interesting behaviors, git is the great example, but the core commit is<br>fundamentally a simple...