One of the real innovations for me in Event Sourcing - not necessarily in terms of technology, but in terms of mindset - has been DCB (Dynamic Consistency Boundary).
Instead of having to define up front how to structure events into streams (typically using aggregates), we technically treat all events within a bounded context as one global stream. That sounds counterintuitive in the beginning, but makes a lot of sense. Letās dive in.
First benefit - this makes those cumbersome technical discussions go away immediately.
Where is the aggregate? How to structure streams?
Where are the boundaries? Looking at the picture above, at some point in time we had to make a decision - āwhat belongs to Customer Management,ā āwhat belongs to Course Subscriptions.ā
Latest when we move to production, this is often set in stone. But things change, business models change, and some of those early decisions turn out to be wrong or at least not ideal.
Thatās also why I refer to aggregates as āstatic consistency boundariesā - changing those decisions later is not impossible, but typically a lot of work, and typically nobody does that. We have to live with past decisions for better or worse, typically.
DCB Changes the Focus
With DCB we focus on āwhat actually happened?ā - the whole big idea of Event Sourcing in general.
But one question has been bothering me - how will this affect Event Modeling? With Event Modeling, we reason about systems, not with engineers - no, with everybody. Itās a visual plan we build. A visual language.
Now that I modeled a few systems with DCB, I found my answer - itās not affected at all. Quite the opposite, everything gets simpler.
Event Modeling has been surprisingly hesitant to change. Which shows how mature it is. Keeping things simple is the hardest thing to do.
Now we can show āwhat actually happenedā - using one swimlane per system / bounded context.
And swimlanes become what they always were meant for - showing the interaction between systems and teams, not stream-design itself.
Payments, for example - thatās a different system managed by a different team. So we show that using swimlanes. They become integration points. Whenever information crosses a lane, we need to pay attention - this is important.
Micro-Decisions and Business Rules
Itās all about consistency.
To execute the command āSubscribe to Course,ā the system needs to know which rules apply.
DCB has not changed that. Letās make an example. Only registered customers can subscribe to a course. We discover those rules in collaboration and express them with Given/When/Then scenarios.
Those scenarios can be expressed easily on the Eventmodelers platform.
Rule 1 - registered customers can subscribe to courses.
Scenario 2 - needs to be registered to subscribe.
Scenario 3 - cannot subscribe twice.
Now, to implement the business logic for a course registration, we need to know which information we need to decide whether a subscription is allowed or not.
How do we know?
Itās the Given/When/Thens that provide this information automatically. We just have to look at the GIVEN part.
This is what I couldnāt wrap my head around in the beginning - how do we model the ādecision model,ā the information the system needs to process a command. The answer that came up surprised me - we donāt. At least I donāt.
Aggregates or DCB - it has no effect on Event Modeling.
The Context for Decisions
With aggregates, it was quite simple - to make a decision you had to load all the events guarded by this one aggregate. Consistency across aggregates required orchestration, the saga pattern, or some steps to handle compensating transactions - this becomes complicated quickly.
Those aggregates can become large over time, and they can become performance bottlenecks. Thatās why we introduce some technical optimizations like snapshotting - think of it like a cache for big aggregates.
With DCB, those decisions become much more granular. We basically just decide on a command-by-command basis what needs to be done.
How that is done varies from framework to framework, from technology to technology. In the Axon Framework, for example, for each command handler you define a Criteria. Think of it like an SQL query to fetch all events necessary to decide whether the command can be processed or not.
āGive me all the events of type Customer Registered for the email, but also all the events of Subscribed To Course for this email and the course ID, the customer wants to subscribe to - so I can check whether a subscription is possible or not.ā
Writing this by hand is cumbersome.
Thatās why we typically generate this code directly from the specifications. AI is really good at that - and the Axon Build Kit for the Eventmodelers platform knows how to translate the Event Model to the executable code.
You focus on the business - the platform takes care of the rest. This especially pays off later, because rules change - adding Given/When/Thens will automatically be reflected in code. Generating the test cases, of course, as well.
Tags Are Indices, Not Domain Concepts
How do you model tags in the Event Model? Probably the question I hear most. You donāt. Tags arenāt a domain concept, itās not essential to the business - itās a technical optimization.
So thereās no place for it in the Event Model.
To be able to query a certain event for a decision in a command handler, it has to be tagged though. How do you express this so AI can generate that?
We use a publicly available and documented schema. This allows anyone to build code generators that can plug into the Eventmodelers platform. And many tools and code generators already do. It has proven to work for years in countless projects.
We typically have two kinds of modeling sessions: discovery and detailed modeling.
In discovery, thereās no place for technical details like tags. Nobody cares. And stakeholders the least.
But later, we might want to add those details to support code generation, often just with engineers before handing the slice to an agent.
In the Eventmodelers platform, you can add meta information to the schema of events, commands, and read models.
One of them we used in the past was the āidā attribute. In the UI, you can specify for each attribute whether itās an identifying attribute. In the code generation, this can be used to identify the stream. Something like a ācustomer id,ā for example, might be a good candidate.
For DCB, I just reuse this attribute for now. We might add a new attribute at some point in time named āindexedā - but Iām slow in changing the public schema, so for now we just reuse the id attribute.
In the UI you can see the id-attributes if you look for the ā*ā.
AI can figure this out by itself pretty well, but I typically want to have a little more control over that. If you use it or not - completely up to you.
In code this becomes something like this.
With the attributes being tagged, they are now basically indexed and can be used in command handlers to make decisions.
Conclusion
With DCB we can put more focus on the business domain itself. Within one context, just model āwhat happened.ā
Inter-context communication - use swimlanes to show how systems integrate and communicate. Showing āintegration,ā not āimplementation.ā
Use Event Modeling to plan, generate code where possible. Use the Build Kit for Axon, for example.
Learn this? Grab the book and the accompanying online course.
Join the Agentic Engineer Program
Apply Spec-Driven Development Hands-On - Event Modeling, Event Sourcing, and AI Engineering with autonomous agents.
Book a Call Today
Want to talk through how Event Modeling could work for your team or project? Letās have a quick, no-pressure conversation.
