Introducing Event Sourcing. Part 1

Translation of the article was prepared on the eve of the start of the course “Java Developer. Professional “

Event sourcing (event sources, event logging, event firing) is a powerful architectural pattern in which all changes made to the application state are saved in the order in which they occurred. These records serve both as a source for obtaining the current state and as an audit trail of what has happened in the application during its lifetime. Event sourcing facilitates decentralized data change and reading. This architecture scales well and is suitable for systems that are already working with event handling or want to migrate to such an architecture.

What is Event Sourcing

Domain experts usually describe their systems as a collection entitieswhich are containers for storing state and events (event)that reflect changes in entities as a result of processing input data within various business processes. Often events are triggered commands (command)coming from users, background processes or integrations with external systems.

Essentially, Event sourcing focuses on eventsrelated to changes in the system.

Many architectural patterns see entities as a primary concept. These templates describe how to save them, how to access them, and how to modify them. Within this architectural style, events are often “sideways”: they are the consequences of changing entities.

Typically, these architectures are based on an entity store such as a relational database or document store. Although events may be present in such an architecture, they, in their essence, are not a primary concept, and can be separated from the entities with which they are associated, as well as hidden behind layers of business logic.

Event Sourcing reverses this approach by focusing on the implementation of events: how they are persisted and how they can be used to obtain the state of an entity. In this case, the database will contain a sequential log of all events that occurred during the lifetime of the system.

Below is a comparison of the Event Store with the Entity Store (more on this later):

Event sourcing, using events as the main architectural concept, is also a domain modeling paradigm that better reflects the customer’s view of the system. Designing systems with an emphasis on events and event logs provides the following benefits:

  • Helps reduce impedance mismatch and the need for concept matching by allowing technology teams to speak the same language as the business when discussing the system.
  • Encourages the separation of responsibilities between teams and requests (command / query responsibility), allowing you to optimize read and write independently of each other.
  • Provides temporality and change history as a matter of course, allowing you to answer questions about how the system looked at certain points in the past and what events happened up to that point.

How Event Sourcing works

Let’s look at a simple example with a bank account. We will have entitywhich is a Bank Account. For simplicity, we will create only one account without identifying it using the account number or in any other way. The account will keep the current balance of funds.

There will be two available for the account commands (command): deposit money (deposit) and withdraw money (withdraw). The commands will indicate the amount to be deposited or withdrawn. We will also define a business rule that verifies that a withdrawal command can only be processed if the requested amount is equal to or less than the current account balance.

With this approach, two events (event) – “Account Credited” and “Account Debited”. These events contain information about the amount that has been deposited or withdrawn. This could be simplified to a single event with a positive or negative sum, but in this example we will split them.

The diagram below shows the data model.

Note that events are “past tense”. They indicate what happened in the system at the time they were written, and are saved only if the command was processed successfully. With this approach, care must be taken not to confuse commands with events. Especially if they mirror each other.

The sequence of commands might look like this:

1.deposit {amount: 100} – deposit 100
2. withdraw {amount: 80} – withdraw 80
3. withdraw {amount: 50} – withdraw 50

The simplest Event Sourcing implementation requires event logwhich is simply a sequence of events. When processing the commands above, you get such a log.

The third command cannot be executed because the requested amount exceeds the available balance.

To get the current balance, the system must process or “generate” events in the order of their occurrence. For our example, it might look like this:

  • bank account {current balance: 0} (starting state)
    bank account {current balance: 0} (initial state)
  • bank account {current balance: 100} (processed: Account Credited, +100)
    bank account {current balance: 100} (processed: Account replenished, +100)
  • bank account {current balance: 20} (processed: Account Debited, -80)
    bank account {current balance: 20} (processed: Funds debited from account, -80)

The current balance is calculated through the processing of all events up to the current moment. Since each event has an implicit timestamp, it is possible to calculate the state of the account at any time by processing all events for the required period of time.

This is a complete (albeit trivial) example of Event Sourcing. In a real system, this example will most likely need to be extended.

It may be necessary to save a sequence of commands to be able to identify how the event occurred, as well as create a separate error event log in which to record commands that failed to complete, for further error handling and maintaining a complete history of successful and unsuccessful teams.

Over time, as the number of commands increases, it may be necessary to maintain the current account balance so that when a withdrawal command is received, it is not necessary to process the full list of events to determine if the command can be executed (i.e., if the account has enough funds). This is an example of a derived store and is essentially the same as an entity store.

Below is how the entity store will look for our example after processing all the commands.

Obviously, compared to a full-fledged Event Store, this is a very primitive example. And this is one of the reasons many developers only use the entity store. In this case, the current account balance is available immediately and there is no need to process all historical events.

However, Event Sourcing does not exclude entity stores. Often, entity stores are present in Event Sourcing projects as well.

End of the first part.

Similar Posts

Leave a Reply