Eventuous is built on a small set of well-defined concepts that map directly to Domain-Driven Design and Event Sourcing principles. Understanding these building blocks — and how they relate to each other — will help you build maintainable, testable, and evolvable systems. The sections below describe each concept, its role in the architecture, and the Eventuous type that implements it.Documentation Index
Fetch the complete documentation index at: https://mintlify.com/Eventuous/eventuous/llms.txt
Use this file to discover all available pages before exploring further.
Events
Events are the source of truth in an event-sourced system. Every state change is represented as an immutable domain event appended to an event stream. Nothing is ever overwritten or deleted — the history of what happened is permanent. In Eventuous, events are plain C#record types decorated with [EventType] to give them a stable, version-independent name in the store:
Aggregate
The aggregate is the consistency boundary for a group of related entities. All business rules and invariants are enforced inside the aggregate. State changes produce events; events are the only way state ever changes. Eventuous provides the genericAggregate<TState> base class:
Apply(evt), Eventuous:
- Appends the event to the internal
Changeslist. - Folds the event into
Stateby callingState.When(evt).
State.When() to rebuild the current state deterministically.
A real aggregate method looks like this:
State
State is a pure, immutable record that knows how to fold a sequence of domain events into the current representation of an aggregate. It has no behaviour — that lives in the aggregate. State is rebuilt from scratch every time an aggregate is loaded. Derive fromState<T> and register event handlers with On<TEvent>() in the constructor:
with expressions to produce new instances — records are never mutated:
State<T, TId> for states that carry an identity property populated automatically by the infrastructure when loading from a stream.
Identity
Every aggregate instance is identified by a typed identity — a strongly-typed wrapper around astring. This prevents accidentally mixing up IDs from different aggregate types at compile time.
Derive from the Id abstract record:
Booking-abc123).
Command Service
The command service is the application-layer entry point. It receives a command, loads the appropriate aggregate from the event store, executes business logic on it, and persists any new events — all in a single unit of work. The strongly-typed base class isCommandService<TAggregate, TState, TId>:
On<TCommand>() registration defines:
InState— whether to create a new aggregate (ExpectedState.New) or load an existing one (ExpectedState.Existing).GetId— a function to extract the aggregate identity from the command.Act/ActAsync— the delegate that calls the aggregate’s domain method.
CommandService<TState> is available when you do not need a full aggregate class.
Event Store
The event store is the persistence abstraction for event streams. Eventuous defines three complementary interfaces:| Interface | Responsibility |
|---|---|
IEventStore | Combined reader and writer |
IEventReader | Load events for a stream by name |
IEventWriter | Append new events to a stream with optimistic concurrency |
Subscriptions
Subscriptions are durable, checkpointed event consumers. They read from an event stream (or all streams) and deliver events to one or more event handlers. Checkpoints are persisted so that processing resumes from where it left off after a restart, providing at-least-once delivery guarantees.Projections
Projections are event handlers that build read models. They consume events from a subscription and write denormalised views to a query-optimised store (e.g., MongoDB, Postgres). Each projection implementsIEventHandler and focuses on a single concern.
Producers
Producers publish events or messages to external message brokers. They implement theIProducer interface and are used either directly or via the Gateway — an event routing component that subscribes to an event store stream and forwards selected events to a broker.
Explore each concept in depth
Aggregates
The
Aggregate<TState> base class, Apply, versioning, and guard methods.State
Immutable state records,
On<TEvent>() handlers, and event folding.Command Services
Command registration, expected state, and the full request lifecycle.
Event Store
IEventStore abstraction and available backend implementations.Subscriptions
Durable subscriptions, checkpoint stores, and partitioning.
Projections
Building and updating read models with MongoDB and other stores.