Introduction
While researching ways to ensure data consistency using NoSQL in systems with frequent reads and writes, I became interested in Event Sourcing and CQRS. During this process, I found a framework called Sekiban, which is designed for Event Sourcing/CQRS, and decided to try it out.
What is Sekiban DCB?
According to the official website, Sekiban is defined as:
"An open-source Event Sourcing and CQRS framework for .NET. It stores not just the current state, but all changes as immutable events."
Within this framework, Sekiban DCB is an Event Sourcing framework that implements a Dynamic Consistency Boundary (DCB). It records all events in a single global stream.
Looking at their documentation, they offer three approaches: DCB Native, DCB Wasm, and Sekiban Cloud (which seems to be still in development and not yet released). For this guide, I will run it using Native C#.
Development Environment & Setup
Prerequisites:
- OS: Windows 11 Pro
- Environment: ASP.NET development environment ready
If your environment is set up, you can create a new project with just a few commands:
# Install the Sekiban DCB templates
dotnet new install Sekiban.Dcb.Templates
# Create project with Decider pattern
dotnet new sekiban-dcb-decider -n MyApp
# Run with Aspire
dotnet run --project MyApp.AppHost
Running the last command will start the Aspire dashboard. The official DCB documentation uses a Student and Class relationship as an example. The default project automatically includes sample code for registering students and enrolling them in classes.
Project Structure
Here is a quick overview of the created project structure:
| Project | Purpose |
|---|---|
DCBNativeProject.AppHost |
Manages dependent services, connections, ports, and startup order. |
DCBNativeProject.ApiService |
Handles API routing and authentication. |
DCBNativeProject.EventSource |
Contains Commands, Handlers, Projectors, and data search processing. |
DCBNativeProject.ImmutableModels |
Defines Student/Class events, Tags, State, and Deciders. |
To give you an idea of how it works, here is the flow for creating and getting a student record.
Creating a Student
- Read the incoming JSON and convert it to a
CreateStudentcommand. - Execute the command using
ExecuteAsync. - Generate a "StudentCreated" event (in this sample, it only uses a
StudentTag). - The framework saves the event to the database.
- Return the result to the user.
Retrieving a Student
- Receive the Student ID and find the target student using the
StudentTag. - Define the expected data state using a
StudentProjector. - Call
GetTagStateAsyncto restore the current state from the past events. - Return the result to the user.
Conclusion
As you can see, database saving operations are completely handled by the framework. I was able to save and load events without worrying about the database code at all.
Next time, I plan to add more Entities and try out some different event registrations!

Top comments (0)