Architecture Spotlight: Event Sourcing, part two

In the previous architecture spotlight entry, we discussed Event Sourcing and illustrated the concept with a simple banking account example. We laid out many of its pros and cons to help readers decide if the pattern would be useful to them.

In this post, we will be expanding the example and showing a working code implementation using a popular event streaming technology, Apache Kafka.

Why Kafka?

However, event sourcing is not Kafka’s only use-case. It was originally designed to support event streaming — high-volume messaging, processing and analytics — so also works well as the general messaging fabric within your microservice system. It is easily scalable, and through its scalability, provides partitioned, replicated storage for the messages you send through it.

Scaffolding the Basic Example

The project described in this article will be built using Spring Cloud, so the first step is to download a project scaffold from Spring Initializr. Once downloaded, edit the project’s pom.xml and add the Spring Cloud Stream Kafka binders to the project’s dependencies list:

You can now build and run the project from the command line, as follows (substitute mvnw for mvnw.cmd on a Windows platform):

Running this will show typical maven build output (including test executions), then log output from the running app. To start with, the log output will consist of the spring boot logo together with a few log messages indicating initial application startup, then shutdown, as right now the application contains no runtime processing logic.

Running Kafka

The easiest way to get started locally is by using docker-compose. A suitable docker-compose.yml file is available (along with several other Spring Cloud Stream Kafka examples for you to take a look at). Once you have downloaded this docker-compose.yml file to your project, simply run:

Running this will start a zookeeper instance (which Kafka requires to orchestrate its clustering), as well as Kafka itself.

Adding the Domain Model



The event type enum:

In addition to credit and debit events, we also include ACCOUNT_OPENED. This is used as a marker to 'open' an account, meaning that an initial account object (with zero starting balance) is created within the system. Credit and debit events can only operate on an already-existing account.

Account events are represented by an AccountEvent class:

Notice the event contains a representation of the latest bank account state within it. This is only done for point-in-time processing convenience and is by no means required. With event sourcing, it’s key to remember that the sequence of all events ultimately represents the master state record. Any other state representation is purely for convenience.

Continue reading this article on

If you need help architecting your next enterprise application or improving your current architecture, please contact us to discuss how we can help!

Originally published at on August 6, 2020.

Modernizing Apps, Tools & Teams | | Twitter: @sitepen