Skip to content

Instantly share code, notes, and snippets.

@eulerfx
Last active April 11, 2025 12:16
Show Gist options
  • Save eulerfx/11227933 to your computer and use it in GitHub Desktop.
Save eulerfx/11227933 to your computer and use it in GitHub Desktop.
Command Sourcing vs Event Sourcing

Both command sourcing (CS) and event sourcing (ES) rely on determinism for correctness.

The correctness condition for ES is the determinism (purity) of the function State -> Event -> State. Given that this function is deterministic, aka it always maps the same inputs to the same ouputs, we can rely on it to reconstitute state at any point in time. Determinism is typically achieved by ensuring that the Event has all required information to make the state transition, ie no side effects. The Event then is a sort of "closure" of all pertinent information about the event.

The correctness condition for CS is the determinism of the function State -> Command -> Event. Herein lies one of the distinctions between command sourcing and event sourcing - a program can control its output, but it not its input. Since one can't control the input, aka command, one can't in general, enrich it with all required information to make the above function deterministic. A consequence of this is that you can't simply replay a stream of logged commands at some arbitrary time and hope to get the same outputs as you would if they were handled immediatly. The other difference of course is that the mentioned ES function is used for reconstituting the state and the CS function is used to react to an incoming command.

Disregard the semantic distinction between commands and events and consider instead the more abstract notion of input and output. In this sense, a service, an aggregate, a projection, etc can all be though of as a programs mapping input to output. In other words, they are all state machines - a finite state transducers in particular. Command sourcing is just State -> Input -> Output. The input need not be thought of as a command and indeed, a command can be thought of as an interpretation of an event as discussed here.

As a practical example, I'm currently building fully event sourced system using EventStore. Output streams produced by some programs are used as input streams of other programs. In this sense, I have both command sourcing and event sourcing.

@yaravind
Copy link

Can you explain the following with an example so that I can have a better understanding

State -> Event -> State
State -> Command -> Event

@nwpointer
Copy link

@eulerfx thanks for this write up, it finally made es/cs 'click' for me if you know what I mean.

@nwpointer
Copy link

@funpluscharity that's notation describing the type of a function. Ie int->bool is a function that accepts a int and returns a bool. State->event->state expresses the idea that events cause a change in state.

@niwrA
Copy link

niwrA commented Apr 6, 2018

I also like commands and events just as a semantic separation of where an approval is necessary, perhaps also on a batch level. An event is then something that you can choose to react to, if you want, but cannot influence.

Ideally the line between UI and store is as direct as possible, so a command should indeed reflect a state change. But either way you should always have some logic that if you replay a command and that triggers sending an email, that email should or should not be sent again for each replay, stuff like that. I don't think you can avoid making that decision for anything IO.

@chrislewis
Copy link

Hi @eulerfx - thanks for the writeup and apologies for a surprise comment on an old post. I'm a bit confused by the use of the word "deterministic" here. You qualify it in this sentence: "... this function is deterministic, aka it always maps the same inputs to the same ouputs", which sounds like you mean "referentially transparent." Is that what you mean?

@pranasblk
Copy link

pranasblk commented Feb 16, 2021

Since one can't control the input, aka command, one can't in general, enrich it with all required information to make the above function deterministic

How about journalling of all commands. Deterministic system using such approach e.g. VoltDB, SLOG (and most decent trading systems e.g. Matching Engines like Nasdaq or best dark pools, Order Management Systems - only low latency ones, and other mostly buy side transaction processors). The reasoning - flow is very predictable and simple, zero-copy processing (network/OS buffer to local store changes) and lower latency using distributed state machines.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment