
An Event Sourcing database for .NET — built with ease of use, productivity, compliance, and maintainability in mind.
Explore the docs »
View Samples
· Report a Bug
· Request a Feature
· Join the Discord
- 📖 Table of Contents
- 🧭 About
- ✨ Key Features
- 🚀 Getting Started
- 🏛️ Architecture
- 📚 Documentation
- 🤝 Contributing
- 💬 Support
- 📊 Repository Stats
- 📄 License
- 🙏 Acknowledgements
Cratis Chronicle is an Event Sourcing database that captures every state change in your system as an immutable sequence of events — rather than storing only the current state. This unlocks powerful capabilities like full audit trails, time-travel debugging, and event-driven architectures without the usual complexity.
Chronicle ships with:
- 🖥️ Chronicle Kernel — the server that manages event storage, processing, and querying
- 📦 .NET Client SDK — a rich C# library for interacting with Chronicle from any .NET application
- 🌐 Web Workbench — a built-in management dashboard for monitoring, browsing events, and administration
- 🗄️ MongoDB Backend — optimized storage layer with an extensible model for other data stores
For core values and principles, read our core values and principles.
| Immutable Event Store | Every state change is persisted as an immutable event — nothing is ever overwritten |
| Event Streams | Organized per aggregate or entity, with full history preservation |
| Schema Evolution | Strongly-typed event definitions with support for evolving schemas over time |
| Rich Metadata | Timestamps, correlation IDs, causation IDs, and custom tags on every event |
| Reactors | React to events as they occur — ideal for side effects and if-this-then-that scenarios |
| Reducers | Imperatively transform events into typed read models, managed by Chronicle |
| Projections | Declarative, fluent read-model builders with join, set, and remove support |
| Observers | Low-level event subscriptions with guaranteed delivery |
| Multi-tenancy | First-class namespace support for isolated tenant data |
| Constraints | Server-side integrity rules enforced at append time |
| Compliance | Full audit trails and data lineage for regulatory requirements |
| Revision | Built-in support for correcting past events |
| Convention-based | Minimal configuration — artifacts are discovered automatically by naming convention |
| DI Native | First-class support for ASP.NET Core dependency injection |
| Strong Typing | End-to-end C# types from events through projections to read models |
| Testing Utilities | In-memory providers and test helpers for unit and integration testing |
Note: The
latest-developmentChronicle image bundles both Chronicle and MongoDB in a single container — no separate database setup needed.
Option 1 — Docker CLI:
docker run -d --name chronicle \
-p 35000:35000 \
cratis/chronicle:latest-developmentOption 2 — Docker Compose:
services:
chronicle:
image: cratis/chronicle:latest-developmentports:
- "35000:35000"# gRPC, REST API and Web Workbench (single TLS port)docker compose up -dAdd the NuGet package to your .NET project:
# ASP.NET Core
dotnet add package Cratis.Chronicle.AspNetCore
# Console / Worker Service
dotnet add package Cratis.Chroniclevarbuilder=WebApplication.CreateBuilder(args).AddCratisChronicle(options =>options.EventStore="MyApp");varapp=builder.Build();app.UseCratisChronicle();app.Run();[EventType]publicrecordUserOnboarded(stringName,stringEmail);[EventType]publicrecordBookAddedToInventory(stringTitle,stringAuthor,stringISBN);// Inject IEventLog or grab it from the event storeawaiteventLog.Append(Guid.NewGuid(),newUserOnboarded("Jane Doe","jane@example.com"));awaiteventLog.Append(Guid.NewGuid(),newBookAddedToInventory("Domain-Driven Design","Eric Evans","978-0321125217"));publicclassUserNotifier:IReactor{publicasyncTaskOnboarded(UserOnboarded@event,EventContextcontext){// send welcome email, provision resources, etc.Console.WriteLine($"Welcome, {@event.Name}!");}}publicclassBooksReducer:IReducerFor<Book>{publicTask<Book>Added(BookAddedToInventory@event,Book?current,EventContextcontext)=>Task.FromResult(newBook(Guid.Parse(context.EventSourceId),@event.Title,@event.Author,@event.ISBN));}publicclassBorrowedBooksProjection:IProjectionFor<BorrowedBook>{publicvoidDefine(IProjectionBuilderFor<BorrowedBook>builder)=>builder.From<BookBorrowed>(from=>from.Set(m =>m.UserId).To(e =>e.UserId).Set(m =>m.Borrowed).ToEventContextProperty(c =>c.Occurred)).Join<BookAddedToInventory>(b =>b.On(m =>m.Id).Set(m =>m.Title).To(e =>e.Title)).RemovedWith<BookReturned>();}Full working samples are available in the Samples repository.
┌──────────────────────────────────────────────────────────┐
│ Your .NET Application │
│ │
│ ┌────────────────────────────────────────────────────┐ │
│ │ Events · Reactors · Reducers · Projections │ │
│ └────────────────────────────────────────────────────┘ │
│ │
│ Chronicle Client SDK │
└─────────────────────────────┬────────────────────────────┘
│ gRPC
┌─────────────────────────────┴────────────────────────────┐
│ Chronicle Kernel │
│ │
│ ┌────────────────┐ ┌────────────────┐ ┌────────────┐ │
│ │ Event Store │ │ Projection │ │ Web │ │
│ │ (MongoDB) │ │ Engine │ │ Workbench │ │
│ └────────────────┘ └────────────────┘ └────────────┘ │
└──────────────────────────────────────────────────────────┘
Chronicle follows a client-server model:
| Component | Description |
|---|---|
| Chronicle Kernel | Server that manages event storage, observer dispatch, projection processing, and querying |
| Client SDK | .NET libraries (Cratis.Chronicle / Cratis.Chronicle.AspNetCore) that connect your app to the Kernel |
| MongoDB Backend | Default event and read-model storage; extensible to other providers |
| Web Workbench | Browser-based dashboard available at https://localhost:35000 when running the development image |
Full documentation is available at https://cratis.io.
| Section | Description |
|---|---|
| Get Started | Quick-start guides for Console, Worker Service, and ASP.NET Core |
| Concepts | Events, projections, reactors, reducers, constraints, and more |
| Hosting | Production and development deployment options |
| Configuration | Client and server configuration reference |
| Contributing | How to build and contribute to Chronicle |
Contributions are what make the open-source community an amazing place to learn, inspire, and create. Any contribution you make is greatly appreciated!
- Fork the repository
- Create a feature branch:
git checkout -b feature/AmazingFeature - Commit your changes:
git commit -m 'Add some AmazingFeature' - Push to the branch:
git push origin feature/AmazingFeature - Open a Pull Request
Looking for a good first issue? Check out the contribute page.
For detailed build and development instructions, see the contributing guide.
You can also browse the code directly in your browser:
| Channel | Details |
|---|---|
| 💬 Discord | Join the community on Discord for questions and discussions |
| 🐛 GitHub Issues | Report bugs or request features |
Distributed under the MIT License. See LICENSE for full details.
- MongoDB — the default storage backend powering Chronicle
- Microsoft Orleans — distributed actor framework used in the Chronicle Kernel
- Louis3797/awesome-readme-template — README inspiration
- All our contributors and the open-source community ❤️