Event Sourcing: Which Comes First, Event or Change?

event-sourcing

I've been researching Event Sourcing, and it seems there are two philosophies hidden within what I've read. The core difference is whether actors in the system are proactive, making changes first and publishing events based on what they have done, or reactive, consuming events and updating data based on those events.

However, the former isn't really Event Sourcing, right? The events aren't the source of change, but just a record of change. That's just an event-based log that can be used to rebuild the data later. When you rebuild the log, you're using different code than when you executed in the first place; in the original run, you send an event that you read the second time around. On top of all of that, you have to introduce commands to actually trigger those changes, which need to be sent directly to the consumer, causing a tighter binding.

Meanwhile, the "reactive" style reverses all of those concerns. Since every change is a reaction to an event, there's basically no difference between listening to the "live" system as it churns on and listening to a replay sometime later. There's no need for explicit "commands", because services aren't told what to do. Rather, they're in charge of maintaining consistency in the face of the events that occur elsewhere, and of notifying others of their own events. The flip side of this is an inversion of control: instead of knowing about other services/aggregates so you can tell them what to do, you just broadcast your event to the system and let them respond according to their rules.
The only comparative downside I see is that you have to explicitly ignore new messages when replaying old messages, but that can be done with configuration/flags.

And yet, many guides and products seem to endorse a proactive style. For example, Event Store expects events to be divided into streams based on their target – meaning there is only one target per event, as if you're either sending it to a single, designated target (which makes it a glorified command) OR because the "target" is really just the source making a record of the action it took.

There must be a gap in my understanding, but after a week or so of reading I haven't come across a well-supported explanation for this. I suppose two questions come out of this:

  1. Which of these two approaches is truly Event Sourcing?
  2. Are there benefits that the proactive approach has over the reactive approach that I haven't mentioned here?

Best Answer

Reminder: it is not your fault that you are confused; the literature sucks.

Which of these two approaches is truly Event Sourcing?

"Event sourcing", as spoken by Event Store, Eventide project, and others, means storing state as a history of events. The event store replaces the RDBMS that we might normally use to remember our history. The history, as represented in an event store, is an append only sequence of events that describe how an entity has changed over time.

When you rebuild the log, you're using different code than when you executed in the first place; in the original run, you send an event that you read the second time around.

Sort of, but not in a way that is significantly different from how we do things in a relational world.

In the world of an O/RM, how do we remember where we are? Typically, when new information arrives, we load our own memory from the database, integrate the new information, and then store our new memory into the database (replacing the old). The old memory is loaded, the new memory is calculated. We store the new memory, and when we next need it, that memory is loaded.

With event sourcing, this basic protocol is unchanged - the significant difference is that we don't replace the old memory, but append new changes to it.

In Pat Helland's terms, event sourcing is about data on the inside; how the domain model in the past shares information with the "same" domain model in the future.

the "reactive" style reverses all of those concerns.... There's no need for explicit "commands", because services aren't told what to do

Not a difference worth worrying about. Messages arrive, the domain model changes, messages depart. Whether you label those messages as commands or events really doesn't matter very much

  • handle(Event) is a command
  • CommandReceived is an event

You can introduce semantic distinctions to separate messages that fan-in toward the authority (commands) from those that fan-out from the authority (events), but from the perspective of the domain the interesting bit is the information that the messages contain, and how the domain model changes in response to that information, not which pattern we think best fits the message.

One idea that may help in all of this is to keep in mind that event sourcing comes from a domain modeling tradition, meaning that we are managing lots of little state machines that have their own private data to track what state they are now in, and their own domain logic to compute what state they should be in next. Think "tell, don't ask" -- we feed new information into the domain model, and it decides for itself what state it should now be in.

Does one service tell another what to do, or does the first simply announce what it did and the second reacts?

This is your key confusion right here - this is a question about a communication pattern. It has nothing to do with event sourcing, which is a data representation pattern.

The most common (or at least, most commonly approved of -- aka "best practice") is that services share information with zero or more subscribers; which is to say that the messages are fan-out. The source service publishes a message, and the subscribers react to it, or not, as they see fit.

(The primary advantage here being that you can add/remove subscribers without deploying a new copy of the source service).

The mechanism of exchange of information between services is a separate concern (a separate design decision) from the arrangement of information within a service.

Related Topic