Skip to content

What's New

Welcome to the official EventSourcingDB blog – your source for announcements, articles, and insights. Here you'll find updates about product releases and improvements, feature announcements, background articles, and practical guidance for working with EventSourcingDB.

Whether you're exploring event sourcing, following the latest changes, or looking for deeper technical insights, this blog keeps you informed.

Java Client SDK 1.0 Now Available

Today we're pleased to announce the release of the official Java Client SDK for EventSourcingDB, version 1.0. If you're building on the JVM, you can now add a single dependency to your project and write your first event from Java a few minutes later.

The SDK is written for modern Java, and it doesn't stop at the client: it brings Testcontainers support for integration tests and a Spring Boot starter that wires everything up for you. In this post, we'll walk you from the first event all the way to a Spring Boot test that runs against a real database.

ArchitectureKit: DDD, CQRS, and Event Sourcing for Go

Last week, we released ArchitectureKit: building blocks for applications based on Domain-Driven Design, CQRS, and Event Sourcing, in Go and on top of EventSourcingDB, open source under the MIT license. If you have been following us for a while, you may remember wolkenkit, our framework for event-sourced applications. ArchitectureKit is the first thing in that tradition we have released since.

It continues that tradition, but as a kit rather than a framework: every piece can be used on its own or left alone, and nothing happens behind your back. What makes it worth a closer look is how it handles the two places where event-sourced applications easily end up relying on luck: two concurrent writes to the same thing on the way in, and a read right after a write on the way out. The easiest way to see both is to follow a single loan, from the request that asks for a book to the moment the catalog shows it as borrowed.

ESDM 0.15.0: Last Call Before 1.0

Ten weeks ago we put ESDM under the MIT license and asked you to tell us what works and what doesn't. ESDM 0.15.0, released last week, is what came back. It is a big release, and most of it traces to someone using ESDM on a real model and reporting what happened: a vocabulary that speaks more than one language, a command that turns a model into a browsable set of pages, a stable way to point at any element from outside the model, and a linter that explains every finding it makes.

Some of it will turn a clean model red, and we expect this to be the last release before 1.0. Both facts belong in the same sentence, because together they are the reason to read on: here is what changed, what breaks and how to fix it, and why the next few weeks are the moment to tell us where we got it wrong.

There Is No Row to Lock

Optimistic locking is one of those techniques you learn once and then use everywhere. A version column, an UPDATE ... WHERE version = 7, and whoever arrives second finds zero rows affected and has to try again. It is cheap, it needs no coordination, and it has kept relational systems correct for decades.

Then you move to Event Sourcing, and the technique has nothing to attach itself to. There is no row that represents the current state, so there is no row to lock. What you would need instead is a condition over a set of records that a query describes – and that turns out to be the one thing a relational database has no single statement for.

Not an Event Yet

Every event stored in EventSourcingDB is a CloudEvent. What your application sends in order to write one is not. It is missing seven of the eleven fields a stored event carries, and if you try to supply them yourself, the database rejects the whole request.

That gap has a name. Internally we call it an event candidate – not an event yet, more like an application to become one. From the outside this looks like pedantry. It is the reason everything else can be trusted. So let's look at what a candidate brings, what the server adds, and why we closed nearly every freedom the CloudEvents standard was generous enough to leave open.

Start With One Table

You have been circling Event Sourcing for a while now: long enough to be convinced by the idea, not long enough to have built anything with it. Today you finally stopped reading and picked one table to start with, the one holding who pays you for which plan. Which is when a colleague asks you why. The table works. The reports run. Nobody has complained. And when you are done, it holds the same values it held that morning, so from the outside, you spent an afternoon achieving nothing.

Eighteen months later, your product owner turns up with a question nobody could have answered before, and you have the answer in twenty minutes, because of what you did that afternoon. This post is both halves of that: first the work that looks like wasted time, in full, with the code, and then what it was for. Everything in it is invented, from the company to the customers to the numbers, but the code is real, and it ran exactly as shown.

PostgreSQL Is Not an Event Store

The table takes about fifteen minutes to write. An ID, a stream name, a version number, an event type, a JSON payload, a timestamp. Add a unique constraint, add an index, and you have somewhere to put your events. It is the first thing almost every team reaches for, and for good reason: the database is already running, already backed up, already monitored, and everybody on the team can read it.

In the previous post we pinned down what an event store actually has to do and held Kafka against that list. This one turns it around and points it at the tool people reach for from the opposite direction – the general-purpose database they already trust with everything else. PostgreSQL passes more of that list than Kafka did, and that is exactly what makes it the harder case. Kafka's central failure announces itself. PostgreSQL fails without a sound, a year in, when a read model is missing a row that nobody can account for.

Your Progress Bar Doesn't Belong in the Event Store

The progress bar works. It fills up, users can see how far along their contract review is, and nobody has complained. Then you open the event store and find 312 events for a single contract, 310 of which nobody would have written if that bar did not have to move.

Nothing is broken, and that is exactly what makes this hard to argue about. The system does what it should, the event names speak the language of the domain, and every one of those events was written on purpose. The unease is real anyway, and if you can't say where it comes from, the discussion ends before it starts. So: most of those events have a shelf life, and the event store is the one place in your system that doesn't.

Compensating Events Won't Save You

A customer calls about their account statement. One line records a payment of 4,800 euros, and nobody at your company can explain where it came from. You look into the event store, and there it is: payment-received, timestamped, hash-chained, immutable. The event is wrong, and it will be wrong forever.

Ask around and you will hear the same answer everywhere: write a compensating event – a new event that reverses the effect of an earlier one, the way a refund reverses a payment. It is good advice, and for two of the three situations that produce a wrong event, it is exactly right. For the third, it makes things worse – and the third is the one nobody warns you about.

Someone Built a Visualizer for ESDM – And It Wasn't Us

In mid-July, we put ESDM under the MIT license and wrote down a sentence that we meant as a principle: because the schema is public, tooling built on ESDM never needs us in the loop. Two weeks later, that sentence turned out to be a prediction instead.

Impierce Technologies, a company in the Netherlands and good friends of ours, built the ESDM Visualizer: an open source web application that turns a folder full of .esdm.yaml files into a board you can walk through, click into, and share as a link. Nobody asked us, and nobody had to. Here is what it is, what it does, and how to have it running against your own model in about a minute.