Skip to content

chronicles-net/chronicles

Chronicles

Event sourcing and CQRS for .NET, backed by Azure Cosmos DB. Chronicles gives you append-only event streams, command handlers, state projections, and document projections — production-ready infrastructure you'd otherwise spend months building yourself.

CI NuGet Branch Coverage Line Coverage Method Coverage

Install

dotnet add package Chronicles

Quick start

// Define your events
record OrderPlaced(string OrderId, string CustomerId, decimal Total);
record OrderShipped(string OrderId, DateTimeOffset ShippedAt);

// Write events to a stream
var streamId = new StreamId("order", orderId);

await writer.WriteAsync(streamId, [
    new OrderPlaced(orderId, customerId, 49.99m),
]);

// Later: append more events
await writer.WriteAsync(streamId, [
    new OrderShipped(orderId, DateTimeOffset.UtcNow),
]);

// Read events back
await foreach (var evt in reader.ReadAsync(streamId))
{
    Console.WriteLine($"{evt.Metadata.Name} at {evt.Metadata.Timestamp}");
}

Three pillars

Event Store

Append-only, immutable event streams persisted to Azure Cosmos DB with optimistic concurrency control.

Type Role
StreamId Identifies a stream by category + id (e.g., "order.42")
IEventStreamWriter Appends events, closes streams, manages checkpoints
IEventStreamReader Reads events, queries streams, retrieves checkpoints

Events are your source of truth — immutable facts stored permanently.

CQRS

Command handlers validate business rules, emit events, and rebuild aggregate state from event history.

Type Role
ICommandHandler<TCommand, TState> Handles a command with full state projection
IStatelessCommandHandler<TCommand> Handles a command without replaying all events
IStateProjection<TState> Folds a stream of events into aggregate state
// Implement a stateful command handler
public class ShipOrderHandler : ICommandHandler<ShipOrder, OrderState>
{
    public OrderState CreateState(StreamId streamId) => new();

    public OrderState? ConsumeEvent(StreamEvent evt, OrderState state) =>
        evt.Data switch
        {
            OrderPlaced p => state with { CustomerId = p.CustomerId, Total = p.Total },
            _ => null,
        };

    public async ValueTask ExecuteAsync(
        ICommandContext<ShipOrder> context,
        OrderState state,
        CancellationToken cancellationToken)
    {
        if (state.CustomerId is null)
            throw new InvalidOperationException("Order does not exist.");

        context.AddEvent(new OrderShipped(context.Command.OrderId, DateTimeOffset.UtcNow));
    }
}

Document Store

Read-model projections driven by the Cosmos DB change feed — query-optimized, denormalized views.

Type Role
IDocumentProjection<TDocument> Projects events into a Cosmos read-model document
IDocumentWriter<T> Creates, updates, replaces, and deletes documents
IDocumentReader<T> Queries documents from Cosmos

Build fast read-side queries without CQRS complexity if you don't need it.

Sample

The sample/ directory contains a food-delivery microservices demo built with .NET Aspire. It covers three bounded contexts — Orders, Restaurants, and Couriers — and shows how to wire up event streams, command handlers, and document projections end-to-end.

Documentation

Guide Description
Getting Started Install Chronicles, configure DI, and write your first events
Event Store Streams, versioning, optimistic concurrency, and checkpoints
Command Handlers Stateless, stateful, and selective-state handler patterns
Projections State projections, document projections, and commit actions
Document Store Reading and writing Cosmos documents with IDocumentReader / IDocumentWriter
Event Subscriptions Change-feed subscriptions and event processors
Event Evolution Schema evolution, event aliases, upcasting, and fault-tolerant deserialization
Dependency Injection Full DI reference: AddChronicles, event store, CQRS, subscriptions
Testing AddFakeChronicles, in-memory fakes, and xUnit test patterns

Contributing & community

About

Chronicles is a comprehensive document and event store C# library specifically designed for seamless integration with Cosmos DB

Resources

License

Code of conduct

Contributing

Security policy

Stars

Watchers

Forks

Packages

 
 
 

Contributors

Languages