Skip to content

Concepts

Sagas vs Process Managers

The moment a workflow spans more than one aggregate or service, someone will say: "We need a saga." It has become the default term for anything that coordinates multiple steps in an event-driven system. Book a flight, reserve a hotel, charge the credit card, and if any step fails, roll everything back. That's a saga, right?

Not quite. What most people describe when they say "saga" is actually a different pattern with a different name, different responsibilities, and different trade-offs. The confusion is not just semantic. It leads to architectural decisions based on the wrong mental model, and those decisions are surprisingly hard to reverse.

Decide, Evolve, Repeat

Almost every Event Sourcing implementation starts with aggregates. You define a class, give it a method for each command, mutate internal state when events are applied, and wire it all up with a framework. This works. Countless systems have been built this way. But if you step back and ask what Event Sourcing actually needs at its core, the answer is surprisingly minimal.

The Decider pattern, introduced by Jérémie Chassaing, strips Event Sourcing down to three functions. No classes. No inheritance. No framework. Just three pure functions that capture everything an event-sourced component does. It is one of the most elegant ideas in the Event Sourcing space, and once you see it, it changes how you think about the entire approach.

The Snapshot Paradox

When developers discover Event Sourcing, one of the first concerns that arises is replay performance. "What if a subject accumulates thousands of events? Won't rebuilding state become painfully slow?" The answer that usually follows is snapshots. Store the current state periodically, and start replaying from there instead of from the beginning. Problem solved, right?

Not quite. In our experience, snapshots are one of the most overrated concepts in the Event Sourcing toolbox. They solve a problem that rarely exists, and when they seem necessary, they often point to a deeper issue that snapshots merely paper over. That's the paradox: the feature designed to optimize performance frequently masks a modeling mistake that, if fixed, would make the optimization unnecessary.

DDD: Back to Basics

A few months ago, I wrote about what went wrong with Domain-Driven Design. In If You Apply DDD to DDD, You Won't Get DDD, I argued that the patterns became the goal, the terminology became a barrier, and the human work got buried under technical abstractions. That criticism stands. But criticism alone is incomplete.

Because not everything in DDD is noise. Strip away the pattern theater, the academic language, the certification industry, and you find a core that actually matters. Commands. Events. State. Aggregates. Ubiquitous Language. Bounded Contexts. These concepts are worth understanding, worth keeping, worth building on. This post is about that core.

The Three-Cent Problem

A few years ago, a bank where we had one of our business accounts lost a transfer of 35,000 Euros. The money left one account but never arrived at the other. It happened between Christmas and New Year, so at first we assumed it was just slow. It was not slow. It was gone.

We complained. We got the money back. We changed banks. So far, so good.

But here is the thing: 35,000 Euros is noticeable. Someone checks the account, sees a missing chunk, raises the alarm. But what if it had been 3 Euros? Or 3 cents? Would anyone have noticed?

Your Aggregate is Not a Table

When developers first encounter Event Sourcing, they bring their mental models with them. Years of working with objects and tables have shaped how they think about data. And so, when they hear the word "Aggregate," something familiar clicks in their brain: an Aggregate must be like an object, and objects map to tables. This intuition feels right. It's also wrong, and it leads to Event Sourcing that looks suspiciously like CRUD with extra steps.

Time is of the Essence

First of all: We wish you a happy new year! We hope you had a wonderful Christmas and an amazing time! 🎉

Speaking of time, let's talk about one of the most commonly misunderstood concepts in event sourcing: when did something actually happen?

If you've worked with events for a while, you've probably noticed that every event comes with a timestamp. In CloudEvents, this is the time field, which EventSourcingDB sets automatically when an event is stored. It's tempting to use this timestamp for business logic. After all, it's right there, readily available. But doing so can lead to subtle bugs and incorrect assumptions. Here's why, and what to do instead.

18 Months of Events Fit on Four Floppy Disks

"Event Sourcing uses too much storage." We hear this all the time. The argument goes like this: since you never delete anything and only append new events, your storage requirements grow indefinitely. Eventually, you'll run out of space. It sounds logical. It's also almost always wrong.

The append-only nature of Event Sourcing is real. But the conclusion that this leads to storage problems is based on three fundamental misconceptions that we see over and over again. Let's examine them, and then look at real production data that might surprise you.

Exactly Once is a Lie

Imagine you're placing an order in an online shop. You click the "Submit Order" button. Nothing happens. You wait a few seconds. Still nothing. So you click again. And maybe once more, just to be sure. Finally, a confirmation page appears. You've successfully placed your order – or have you? Did you place one order, or three?

This scenario plays out millions of times every day across the internet, and it reveals one of the most persistent myths in distributed systems: the promise of exactly-once delivery. Message queues advertise it. Streaming platforms claim it. Enterprise architectures depend on it. But here's the uncomfortable truth: exactly-once delivery is impossible in distributed systems. The good news? That's perfectly okay, and there are practical ways to handle it.

Proving Without Revealing: Merkle Trees for Event-Sourced Systems

Imagine it's January 2026. You run a platform with millions of users. An auditor walks in with a specific request: "Show me proof that you captured a GDPR consent event for user #12847 on March 15th, 2024." You know the event exists – it's sitting in your event store. But here's the problem: you can't just hand over your complete event log. That log contains millions of events with sensitive customer data, financial transactions, business secrets, and personal information from thousands of other users.