Akka Event Sourcing – Modeling Intuitions & Caveats

A few less-than obvious observations

After spending almost one year developing applications on top of Akka Event Sourcing (ES), I would like to provide some insights & caveats derived from my hands-on experience. I will provide caveats because this type of information is what is harder to find. Akka ES is a good framework, Lightbend provide extensive documentation, so all the positive aspects are covered and easy to find.

Akka Persistence enables stateful actors to persist their state so that it can be recovered when an actor is either restarted, or migrated within a cluster. [1]

Event Sourcing programming model

The programming model for Event Sourcing is:

• Send a command to an event-sourced behavior (Akka actor). Think of the command as “Change your state!”

• The actor examines the command (in its command handler), and if it appropriate to execute it, creates an event from it and hands the event over to the Akka framework to be persisted. Think of this event as “My state has changed”, containing pretty much the same information as the command, but with different semantics

• Once the event is persisted, the Akka framework provides the event back to the actor’s event handler, to be applied to modify the state of the actor

In case of a crash, the state of an event-source behavior actor is reconstructed by applying all events from the beginning of time (or, more realistically: from the last snapshot). This is where the first caveat applies: what if the structure of events in code is now different from the persisted historical events?

Backwards compatibility of stored events – event evolution

Some design thinking is necessary here, because the Akka events are stored in an opaque, proprietary format. If the current version of the events has a different number of fields, or different datatypes for them, or different validation rules for them, then your application needs to be able to deal with event schema versioning [2].

The command that broke the camel’s back

How would you model “the straw that broke the camel’s back” in Akka? You would not implement a command named “Break the camel’s back”. Obviously, the command is “Add straw”, which creates the events “Straw added” and “Camel back broken”. If you can excuse the animal cruelty image, we have discovered “spontaneous events”, i.e., events that occur because of a combination of internal state and external stimulus (command). There are physical analogues of this pattern: neurons fire when the positive sodium charges reach a certain level; electrons emit photons and descend energy levels. The modeling takeaway here is to be mentally ready to create event models where (1) events are determined by stimulus (command) + current state (2) a single command can generate more than one event. Both of these situations are supported by Akka.

Diamonds are not a developer’s best friend

Imagine leaving on a family vacation and needing to get gas and drinks for the trip. Clearly, you can get gas and drinks in any order. The state of your trip then becomes (depending on the order of events): “Got gas, need drinks” or “Got drinks, need gas”, and finally “Ready”. If you graph the state transition diagram, you get a diamond with root at “Need gas and drinks”, two different branches (depending on which event happens first) and converging at “Ready”. The modeling challenge here is to include in your state diagram as many states as needed to express the situation. It’s easier with two intermediate states as shown here, but it would get more complicated if there were numerous intermediate states.

So you are married now?

There is a small modeling semantic that distinguishes Akka events from real-life events. When you emit the event “Got married”, you have signed the papers, had the ceremony and taken the photos. In Akka, the “Got married” event is persisted to the DB as a result of the “Get married” command, then it is passed to the actor’s event handler, which modifies the actor’s state. To continue the analogy, it is only now that the actor proposes to their future spouse, books the venue, etc. This is all to convey an intuition of when things “actually happen” (i.e. the actors’ state changes) in Akka. Because of this, you can also think of Akka events as “internally generated commands”. The Akka documentation invites us to think of the command as “Get married”, and the event as “Got married”. But the actual semantics of the event (given when it is applied to the actor) is “Ok, now get married for real”.

References

[1] https://doc.akka.io/docs/akka/current/typed/persistence.html

[2] https://leanpub.com/esversioning/read#leanpub-auto-why-version