Kill Aggregate? An Interview on Dynamic Consistency Boundaries¶
Golo: Bastian, you are working as a freelancing software developer with a focus on Domain-Driven Design (DDD), Event Sourcing, and related topics. And you've been advocating for Dynamic Consistency Boundaries (DCB) for a while now. Can you tell us a bit about your background and how you got into this space?
Bastian: Gladly! Like many developers of my generation, my journey actually started sitting in front of a Commodore 64. I vividly remember the wonder of writing little BASIC scripts. They were completely useless, practically speaking, but they gave me my first taste of pure creativity. That feeling of staring at a blinking cursor and creating something from a clean slate stuck with me.
Professionally, things kicked off around the turn of the millennium. I was working as a software engineer when we needed a Content Management System. That's how I encountered TYPO3 and eventually joined the core team, which gave me my first deep exposure to open source work and the realities of maintaining large, long-lived code bases.
A few years later, I joined a group that was formed to explore what a modern successor to TYPO3 could look like. That initiative eventually became Neos CMS. We were tasked with building a new foundation using contemporary best practices, right as Eric Evans' "Blue Book" was gaining traction. Inspired by it, we built what was essentially a "DDD framework."
Looking back, we were incredibly ambitious and breaking new ground for the PHP ecosystem at the time. Naturally, that meant we had to learn some lessons the hard way – especially regarding the balance between tactical patterns and strategic design. But that experience sparked my long-term fascination with Domain-Driven Design. When I stumbled upon Event Sourcing, it immediately resonated with me. Today it's my default approach, and I've built many libraries and applications around it.
The Limits of Aggregates¶
Golo: In Domain-Driven Design, the aggregate pattern has been the go-to approach for defining consistency boundaries for decades. It's well understood, well documented, and supported by virtually every framework out there. Yet at some point, you started questioning whether aggregates are always the right tool for the job. What was the moment when you realized that traditional aggregates were hitting their limits? Was there a specific project or problem that triggered this?
Bastian: The Aggregate pattern, as Eric Evans described it, is genuinely useful for reasoning about consistency and it simply makes explicit the invariants that exist in your domain anyway. But I think we've conflated the concept with the implementation. In the Event Sourcing world, Aggregates often cause more confusion than clarity in my experience and I would boldly challenge the idea that its implementation is truly "well understood".
One of the core frictions for me was always the requirement to distribute events across multiple rigid event streams when, from a logical perspective, there's really just a single timeline. And once you start working with real-world requirements, you quickly run into cases where the classical event-sourced aggregate makes simple things surprisingly difficult. Enforcing global uniqueness or preventing double spending are good examples. They sound straightforward, but they're not when you're constrained by strict aggregate boundaries.
The usual advice in these situations is to coordinate multiple aggregates or to "embrace eventual consistency" to enforce business constraints. But that often turns what should be simple workflows into unnecessarily complex processes. There are certainly domains where that complexity is justified, or even required. But I honestly haven't worked on a single Event Sourcing project where the aggregate approach didn't introduce accidental complexity at some point.
There is also the "Gravity" problem. Aggregates tend to be greedy. They attract domain logic like a black hole until they become massive God Objects that are hard to split. And technically, they are greedy because writing to an Aggregate locks the entire stream, serializing operations that might not actually conflict with each other.
Discovering DCBs¶
Golo: So you had experienced the pain firsthand. At some point, you came across the concept of Dynamic Consistency Boundaries, a term that Sara Pellegrini coined in her famous talk "Kill Aggregate!". How did you discover DCBs, and what was your initial reaction? Were you skeptical at first, or did it immediately click?
Bastian: I don't recall exactly how I first came across Sara's presentation, but I remember my initial reaction clearly: It instantly made sense to me because I could see how her approach offered a solution to the exact friction points I was battling.
At that point, though, it was just a theory – I wasn't sure how feasible what later became known as DCB really was. So I started experimenting and created a first, fairly naive implementation of a compatible event store using a relational database.
After that, I got in touch with Sara, who turned out to be not only as incredibly sharp as I had expected but also very open-minded. We spent countless hours discussing the concept and iterating on potential APIs, which helped refine both my understanding and the practical approach.
DCB in a Nutshell¶
Golo: Let's say someone is already familiar with Event Sourcing and aggregates, but has never heard of DCBs. If you had to explain the concept in about two minutes, what would you tell them?
Bastian: If someone already knows Event Sourcing and aggregates, I usually start by saying: Forget the notion of fixed event streams. In DCB, there is essentially just one global event stream per event store. You can still have multiple event stores in an application, but within each store there's only a single, ordered timeline.
Likewise, events don't have a version per stream. An event simply has its global sequence position. Instead of grouping events into separate streams, we associate them with domain instances – usually entities – using what we call tags.
So rather than appending a CourseRenamed event to a stream like course-123, you attach a corresponding tag to the event. And here's the important part: an event can have multiple tags, which essentially allows us to slice and dice history in multiple dimensions, not just one.
For enforcing consistency we're still using optimistic locking, but the way it's applied is a bit different. We still rebuild in-memory state – but instead of pulling all events from a predefined stream, the event store lets you query exactly the events relevant for this single decision. We call the resulting snapshot the Decision Model.
If the business rule passes, we append the new event. But here is the magic: instead of saying "I expect the stream version to be 5" we say, "I made a decision based on this specific Query and I considered events up to Global Sequence 5000" If any new event matching that query arrived in the meantime, the write fails.
You can think of that Query as a dynamic, temporary stream that exists only for the duration of a single interaction with your application. That's where the "Dynamic" in Dynamic Consistency Boundaries comes from.
Common Misconceptions¶
Golo: That's a helpful explanation. But whenever a new concept emerges, there's often a gap between what it actually means and what people think it means. What are the biggest misconceptions you encounter when developers first hear about DCBs?
Bastian: There are definitely a few recurring themes that spark heated discussions. One common misunderstanding is that DCB means "no modeling" or "chaos." People hear "dynamic" and think we are just throwing events into a pile without structure. The opposite is true: DCB requires more explicit modeling because you can't rely on the crutch of an "Aggregate Bouncer" to catch everything.
Another misconception is that you have to strictly choose between DCB and Aggregates. The reality is that DCB is a superset. You can actually implement a classic Aggregate on top of a DCB architecture if you really want to. I just usually find out you don't need to.
I've also heard the argument that if you just model your aggregates around processes rather than nouns, you wouldn't need DCB in the first place.
And finally, there is the fear that moving away from static boundaries automatically increases complexity, whereas my experience has been quite the opposite.
Trade-offs¶
Golo: I think it's important to acknowledge that aggregates do have real advantages: they provide clear boundaries, a simple mental model, and they're easy to reason about. So when switching to DCBs, what do you actually lose? And are there situations where the trade-off simply isn't worth it?
Bastian: On the surface, you lose the "One Lock Fits All" simplicity. With an Aggregate, you don't have to think about concurrency; you just lock the ID and you are safe. You also lose the obvious "folder structure" aspect where, if you have an Account aggregate, you know exactly where to put the ChangePassword method. In DCB, because we focus on processes and behaviors rather than nouns, the code is organized differently, which can be disorienting at first.
However, in my honest opinion, those perceived advantages are actually fallacies. Aligning Aggregates strictly with entities is incredibly tempting and feels simple at the start, but it almost always leads to inflexibility and accidental complexity down the road.
If your domain is simple enough that a strict, noun-based grouping works perfectly without friction, you are likely dealing with a pure CRUD application. And if that's the case, I wouldn't recommend using an Event-Driven Architecture to begin with. But for any system complex enough to warrant Event Sourcing, the "simple" entity-based approach usually becomes a trap.
Domain Modeling with DCBs¶
Golo: That's an honest assessment. Now, when consistency boundaries are no longer static but determined dynamically, I imagine this changes how you think about domain modeling altogether. How does your approach to modeling a domain shift when you embrace DCBs?
Bastian: That is a very important question. To me, DCB is just a small piece of the puzzle, where the main goal is to make building reliable and maintainable software simpler. That said, DCB removes the technical friction, so I can focus purely on the business intent.
I stop thinking about "How do I fit this command into that Object?" and start thinking "What facts do I need to check to allow this Command?". This naturally supports process-oriented thinking, which aligns much better with Event Sourcing than structural, noun-oriented thinking in my opinion.
I usually organize my code into composable Atomic Projections. These are small, pure functions that calculate a specific state – like Course::capacity(courseId). When combined with an architecture that strictly separates domain logic from infrastructure, such as Hexagonal Architecture, it greatly reduces the number of building blocks you need. The resulting core domain code becomes almost declarative, which opens up a whole new world of opportunities that we are currently exploring.
Technical Requirements¶
Golo: Let's talk about the technical side. DCBs aren't just a conceptual shift; they also place specific demands on the underlying infrastructure. What technical requirements does an event store need to fulfill to make DCBs practical and performant?
Bastian: We tried to keep the footprint minimal. A DCB-compliant store needs to support tagging (or filtering by payload properties) and, crucially, conditional appending based on a query.
It needs to guarantee that if I say "Append this event, but only if no other event matching Query X has appeared since Position Y", the store can enforce that thread-safely. (Editor's note: EventSourcingDB supports this with both EventQL and the isEventQlQueryTrue precondition.)
Scalability¶
Golo: One thing that worries some developers is the idea that consistency boundaries are determined at runtime rather than being fixed upfront. How do you handle that complexity in practice? Doesn't it get confusing quickly, especially in larger systems? In other words: how well do Dynamic Consistency Boundaries scale?
Bastian: Contrary to what one might expect, consistency boundaries don't become less strict with DCB – in my experience, they actually become more explicit. The main differences are that the boundaries are no longer carved into the persisted data, meaning they can evolve over time, and they can overlap. This actually scales better in many cases. Because you are only locking the specific "slice" of history relevant to a command, you have fewer collision conflicts than with coarse-grained Aggregates.
As for cognitive load, I find it handles complexity better because coupling becomes more explicit. This ensures the architecture remains flexible, since it becomes much easier to split parts of an application into their own Bounded Contexts, or even into completely independent services, if complexity grows beyond a manageable level.
Performance-wise, I was initially unsure how well a DCB-compliant event store would hold up, but I've since seen implementations that exceed the throughput of traditional event stores, even with millions of events and thousands of parallel consumers.
Real-World Experience¶
Golo: Theory is one thing, but real-world experience is another. Do you have a concrete example from an actual project where using DCBs made a significant difference, something that would have been much harder or even impossible with traditional aggregates?
Bastian: I've had the chance to battle-test these ideas in a number of production projects over the last two years. Unfortunately, I can't share specific client details publicly, though people should feel free to get in touch if they want to hear more about the concrete use cases.
What I can say is that the new approach made a massive difference in all of them. We realized quickly that operations affecting multiple entities are not edge cases – they are actually the norm in complex domains. In a traditional setup, enforcing consistency across these entities used to be a nightmare, often requiring Sagas or Process Managers. With DCB, those scenarios became trivial, and the accidental complexity dropped significantly.
We are collecting these common patterns, and I'm sure they will look very familiar to anyone who has worked with Event Sourcing long enough.
Looking Ahead¶
Golo: Looking at the broader picture: do you think DCBs will eventually replace aggregates as the standard approach, or do you see them coexisting, each serving different use cases?
Bastian: Personally, I don't think I will ever create an event-sourced aggregate class that encapsulates command handling again. To me, that feels similar to the Active Record pattern, which I stopped using a long time ago. Making decisions based only on the specific state needed for a given operation feels much more natural to me.
But that's just my personal take, of course. I really can't speak for others, and I wouldn't dare to make any industry-wide predictions.
Adoption and Ecosystem¶
Golo: If DCBs are as powerful as you describe, one might wonder why they haven't gone mainstream yet. There's already dcb.events, a community resource that you and Sara maintain, but what else is still missing in the ecosystem (in terms of tooling, documentation, or community awareness) for DCBs to become more widely adopted?
Bastian: I don't know for sure, but I have some assumptions. First, while DCB isn't strictly limited to Event Sourcing, that is its primary use case – and Event Sourcing itself is not yet mainstream (wrongly so, in my opinion). So DCB is effectively a niche within a niche right now.
Second, DCB isn't just a different coding practice; it requires a compatible event store and a shift in mental models. I'm not surprised that this creates some inertia regarding adoption. The concept is also relatively new, as Sara's presentation was published just over two years ago.
That said, the ecosystem is growing. There are already a couple of compatible event stores, including ones from big players, and new implementations are sprouting up constantly. Our website is meant to be an open hub for discussions and tools, and everyone is more than welcome to provide resources or join the conversation. So don't hesitate to reach out, whether you're as excited about this direction as we are or you'd like to put the idea to the test!
Golo: Bastian, thank you for sharing your insights.
Bastian Waidelich is a freelancing software developer from Cologne, Germany, with a focus on Domain-Driven Design (DDD), Event Sourcing, and related topics. For more information or to get in touch, visit wwwision.de.