Event stores and event sourcing: some not so practical disadvantages and problems

TL;DR

This post is some kind of answer to the article mentioned in a tweet by Greg Young. The blog post of the author has no comment section. Also, this post contains a lot of information, so that’s why I’m posting it instead of sending as an email or DM.

Commits

Typically, an event store models commits rather than the underlying event data.

I don’t know what is a typical event store. I know though that:

  1. EventStore built by Greg Young company, a standalone event database, fully separates these two, providing granularity on the event level
  2. StreamStone that provides support for Azure Table Storage, works on the event level as well
  3. Marten , a PostgreSQL based document&event database also works on the singular event level

For my statistical sample, the quoted statement does not hold true.

Scaling with snapshots

One problem with event sourcing is handling entities with long and complex lifespans.

and later

Event store implementations typically address this by creating snapshots that summarize state up to a particular point in time.

and later

The question here is when and how should snapshots be created? This is not straightforward as it typically requires an asynchronous process to creates snapshots in advance of any expected query load. In the real world this can be difficult to predict.

The first and foremost, if you have aggregates with long and complex lifespans, it’s your responsibility because you chose a model where you have aggregates like that. Remember, that there are no right or wrong models, only useful or crappy ones.

The second. Let me provide an algorithm for snapshoting. If you retrieved 1000 events to build up aggregate, you should snapshot it (serialize + put into cache in memory + possibly store in a db). Easy and simple, I see no need for fancy algorithms.

Visibility of data

In a generic event store payloads tend to be stored as agnostic payloads in JSON or some other agnostic format. This can obscure data and make it difficult to diagnose data-related issues.

If you as an architect or developer know your domain and you know that you need a strong schema, because you want to use it as published interface but still persist data in JSON instead of some schema-aware serialization like protobuf (binary, schema-aware serialization from Google) it’s not the event store fault. Additionally,

  1. EventStore
  2. StreamStone

both handle binary just right (yes, you can’t write js projections for EventStore, but still you can subscribe).

Handling schema change

If you want to preserve the immutability of events, you will be forced to maintain processing logic that can handle every version of the event schema. Over time this can give rise to some extremely complicated programming logic.

It was shown, that instead of cluttering your model with different versions (which still, sometimes it’s easier to achieve), one could provide a mapping that is applied on the event stream before returning events to the model. In this case, you can handle the versioning in one place and move forward with schema changes (again, if it’s not your published interface). This is not always the case, but this patter can be used to reduce the clutter.

Dealing with complex, real world domains

Given how quickly processing complexity can escalate once you are handling millions of streams, it’s easy to wonder whether any domain is really suitable for an event store.

EventStore, StreamStone – they are designed to handle these millions.

The problem of explanation fatigue

Event stores are an abstract idea that some people really struggle with. They come with a high level of “explanation tax” that has to be paid every time somebody new joins a project.

You could tell this about messaging and delivery guarantees, fast serializers like protobuf or dependency injection. Is there a project, when a newbie joins, they just know what and how to do it? Nope.

Summary

It’s your decision whether to use event sourcing or not, as it’s not a silver bullet. Nothing is. I wanted to clarify some of the misunderstandings that I found in the article. Hopefully, this will help my readers in choosing their tooling (and opinions) wisely.

Snapshot time!

It’s snapshot time! There’s been a lot of event sourcing content so far. Let’s do a recap!

Below you will find a short summary of event sourcing related articles that I have published here so far. Treat it as a table of content or a lookup or a pattern collection. It’s ordered by date, the later – the older. Enjoy!

  1. Why did it happen – how to make your event sourced system even easier to reason about
  2. Event sourcing and interim stream – how to embrace new modelling techniques with short living streams
  3. Multitenant Event Sourcing with Azure – how to design a multitenant event sourced system using Azure Storage Services
  4. Rediscover your domain with Event Sourcing – how to use your events and astonish your business with meaningful insights
  5. Event Sourcing for DBAs – a short introduction for any relational person into the amazing world of event sourcing. Can be used as an argument during a conversation.
  6. Enriching your events – what are events metadata and why should we care? how to select the most important ones
  7. Aggregate, an idempotent receiver – how to receive a command or dispatch an event exactly once?
  8. Process managers – what is a process manager, how can you simplify it?
  9. Optimizing queries – how to make queries efficient, especially when dealing with multiple version of the same application running in parallel
  10. Event sourcing and failure handling – an exception is thrown. Is it an event or not? How to deal and model it?
  11. Embracing domain leads towards event oriented design – how event oriented design emerges from understanding of a domain

Why did it happen?

TL;DR

Do you know that feeling of being powerless? Of being not able to tell why your system acted in a specific way? Of not being able to recognize whether it’s a hacker or your system malfunction? Event sourcing, by storing all the events that happened in your system helps a lot. Still, you can improve it and provide much better answers for ‘why did it happen?’.

Why?

The question ‘why did it happen?’ reminds me of one case from my career. It was a few years back, when I was a great fan of AutoMapper. It’s a good tool, but as with every tool one should use it wisely (if you have only a hammer …). I think I stretched it a little to much and landed in a point where nobody was able to tell what the mapping come from. It took only 3 days to provide an extension method Why that was showing which mapping will be applied for a specific object.

I’d say, that being able to answer these ‘whys’ within a reasonable time frame is vital for any project. And I don’t mean only failures. When introducing a junior to your team, being able to show how and why things work is important as well.

Event sourcing

Event sourcing helps a lot. It just stores every business delta, every single change of your domain objects. You can query these changes in any time. You can improve your queries even more by enhancing events with some metadata (which I covered recently in here). There’s a case though that you should consider to tell if the reasoning is always that easy.

Dispatching an event

Some of actions on your aggregates are results of dispatching an event. Something happened and another part of your systems turns that into an action. For instance consider the following

When OrderFinished then AddBonusPoints

Some bonus points are added to an account whenever an order is finished. When looking at an account history, you’ll see a lot of events BonusPointsAdded. Yes, you could introduce a lot of events like BonusPointsAddedBecauseOfOrderFinished but this just leaks the process into your account aggregate. If you don’t do it, can you answer the following question

Why BonusPointsAdded were appended?

Because somebody added points? Yes, but WHY? It looks that the reason is disconnected.

Point back

What if following metadata were added to every event that is a result of another event. In this case, what if the following metadata were added to this specific BonusPointsAdded

enhance

Now, when somebody asked Why did it happen you can easily point to the original event. If that was a reason of some process, of dispatching the event you can follow the link again and again to find the original event that was created because of an user action.

Summary

Links are a powerful tool. If you use it with event sourcing you can get a history of your system that’s easy to navigate, follow and reason about.

Event Sourcing and interim streams

TL;DR

When modelling with event sourcing, people often tend to create long living streams/aggregates. I encourage you to improve your modelling with interim streams.

Long live the king

A user, an account, a company. Frequently this kinds of aggregates are distinguished during first modelling attempts. They are long lasting, never ending streams of events. Sometimes they combine events from different contexts, which is a smell on its own. The extended longevity can be a problem though and even when events are correlated and an aggregate is dense, in the business meaning, rethinking it’s lifetime can help you design a better system.

Interim streams

One of the frequent questions raised when applying event sourcing is: how do I ensure that a user is registered with a unique email? For sure in majority of cases handling duplicates by a person would be just enough (how many people would actually try to register twice…), but let’s try to make this a real business requirement.

Because of the disability to span a transaction across different streams, we can model this requirement in a different way. Let’s start with creation of a stream which name is derived from email, like:

useraggregate_email@domain.com

This would ensure, that for a specific email, only one aggregate can be created. Next step is to put an event holding all the needed data to add a user, like:

UserRegistered:

{name: “Test”, surname: “Test”, phone: “111111111111”, userid: “some_guid”}

The final step is to have a projection that consumes this event and appends it to a new stream named:

useraggregate_some_guid

This ensures that we don’t use a natural key and still preserve the uniqueness requirement. At the end we have an aggregate that can be identified with its GUID.

Time to die

The interim stream example with the unique email wasn’t the best one, but was good enough that a stream can make interim streams or that can be based on an interim stream. It’s vital to liberate from thinking that every stream needs to live forever. I’d say that in majority of cases there’s a moment when a stream needs to ends its life.

stocksnap_6qj9xjwicj

The longevity isn’t the most important virtue of a stream. It’s created either to model a behavior in a right way or be just a passage for other streams. Next time when you model a stream ask yourself, how long will it live?

Event Driven Architecture – feed your head

It’s been a few days since the last Warsaw .NET User Group meeting. The main presentation was provided by me & Tomasz Frydrychewicz. The title was: “Event Driven Architecture in practice”. Being given a high number of answers to the pool and the overall was very positive response I may call it one of my best presentations ever. Anyway, I was being asked many questions during these days, the main one is what/who should I read/watch to immerse into this event-based approach. The list below tries to answer it somehow, grouped by author:

  1. Martin Fowler
    1. http://martinfowler.com/eaaDev/EventSourcing.html – the top 1 Google search result. Martin provides a good intro, mixing a bit a concept of storying commands and events. Anyway, this is a must read if you starts with this topic
    2. http://martinfowler.com/eaaDev/RetroactiveEvent.html – the article which one should become familiar with after spending some time with event modelling. Some domains are less prone to result in special cases for handling this kind of events, other may be very fragile and one should start with this
  2. Lokad, CQRS, Rinat Abdullin
    1. http://lokad.github.io/lokad-cqrs/ – a must-read if you want to choose the event way. Plenty of materials and tooling. To me some parts are a bit frameworkish, but still, it’s one of the best implementations I’ve seen. Understanding this might be your game changer.
      Additionally, it provides an Azure storage implementation.
  3. Rinat Abdullin & Kerry Street
    1. Being the worst – how to become a master? Immerse yourself in a new field as the worst. That’s how winning is done! Am amazing journey through learning about DDD, Event Sourcing and many paradigms.
  4. Microsoft Patterns and Practices:
    1. CQRS Journey – a free book about a group of developers using event driven approach with DDD in mind, to build a new system. I love the personas they use to drive dialogues between different opinions/minds/approaches. It’s not a guide. I’d rather consider it a diary of all the different cases you can meet when implementing solutions using these approaches.
  5. Event Store
    1. The whole Event Store database is an actual event store for storying events from the event sourced systems. I encourage you to spend a week or more on reading its code. It’s a good codebase.
    2. Event sourcing documentation is a short introduction to the ES world. After all these years, it still uses the Word generated pictures 🙂 but this doesn’t diminish its value.
  6. NEventStore
    1. NEventStore is an open source library for storying and querying your events. It’s opinionated, for instance it stores all the events as one commit object. I’ve read it carefully, although I don’t like its approach still. One should read it though, it’s always worth to know what’s already provided.

It’s a bit long list but nobody said that you can learn a new paradigm over one weekend. So read, learn and apply it successfully 🙂

Optimisation of queries against event-sourced systems

I hope you’re familiar with event sourcing pattern. Switching from update-this-row to a more behavioral paradigm in designing systems, that’s one of the most influential trends for sure. But how, a system storing only business deltas/events can be queried? Can it be queried at all?

Project your views

To answer this need you can use projections. It’s nothing more than a function applied to all, or selected events (by stream id, event category, or any dimension you can get from the processed event). The similar solution one can find in Lokad CQRS which is described in this post. So yes, there is a way of applying all the needed events on a view/projections, which can be queried the given parameters. Is there a way of optimizing the queries responses?

Fast response

For sure there is! Let’s take into consideration a projection replying all events for users changing their personal data, but applying only these, which modify their user name. This is probably a very infrequent operation. The projections stores id->name map, which is used for various services to display the user friendly name. What can be done to improve the service performance storing this kind of mapping?

Consider storing two event sequence numbers:

  1. for remembering to which index the events were scanned
  2. for remembering the last user related event which actually changed the mapping

The second can be easily used to ETag all the responses. If the operation is infrequent, the responses can be 304ed easily for long periods of time. This ETag based optimization can be applied always. The more sparse projection state changes, the better chance of reusing the client cached response.

Event sourcing and failure handling

Currently I’m workingwith a project using event sourcing as its primary source of truth and the log in the same time (a standard advantage). There are some commands, which may throw an exception if the given condition is not satisfied. The exception propagates to the service and after transformation is displayed to the user. The fact of throwing the exception is not marked as an event. From the point of consistency it’s good: an event isn’t appended, the state does not change, when an exception occurs. What is lost is a notion of failure.
A simple proposal is to think a bit more before throwing an exception and ending a command with nothing changed. One may append a ThisCriticalCommandFailedEvent with nothing but the standard event headers (like time, user performing command, etc.) or something with a better name and return a result equal to the exception thrown. The event can be used later, when you want to analyze failures of executing commands.