An open-source (MIT) event-sourcing database and runtime — Orleans-based .NET kernel, pluggable storage (MongoDB default; PostgreSQL, SQL Server, SQLite, in-memory), and language-agnostic gRPC contracts with clients for .NET, TypeScript, Kotlin/Java, and Elixir (Python coming soon).
Explore the docs »
View Samples
·
Report a Bug
·
Request a Feature
·
Join the Discord
- 📑 Table of Contents
- 📖 About
- ✨ Key Features
- 🌍 Clients
- 🚀 Getting Started
- 📐 Architecture
- 📚 Documentation
- 🧩 The Cratis ecosystem
- 🤝 Contributing
- 💬 Support
- 📊 Repository Stats
- 📄 License
- 🙏 Acknowledgements
Cratis Chronicle is an event-sourcing database and processing runtime with a first-class .NET SDK and additional TypeScript, Kotlin/Java (JVM), and Elixir clients — with a Python client coming soon — plus pluggable storage-provider implementations including MongoDB (default), PostgreSQL, SQL Server, and SQLite.
Chronicle 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 is free to use and MIT licensed.
Chronicle is built on a simple conviction: event sourcing is worth it for almost any system dealing with information and business flows — so it should feel like the code you already write. Events, reactors, reducers, and projections are plain, idiomatic types, familiar even if you have never event-sourced before, with conventions designed to remove friction and boilerplate. That intent — productivity, quality, and reliability in one deliberately simple ecosystem, AI-friendly by design and with free AI skills — runs through everything Cratis ships.
Chronicle ships with:
- ⚙️ Chronicle Kernel — the server that manages event storage, processing, and querying, built on Microsoft Orleans for distributed, stateful processing
- 🧩 .NET Client SDK — a rich C# library for interacting with Chronicle from any .NET application
- 🌍 Language-agnostic gRPC contracts — protobuf contracts that any language can implement, with clients for TypeScript, Kotlin/Java, and Elixir, and a Python client coming soon
- 🗄️ Pluggable storage — MongoDB (default), PostgreSQL, SQL Server, SQLite, and in-memory providers
- 🖥️ Web Workbench — a built-in management dashboard for monitoring, browsing events, and administration
- ⌨️ CLI — the Cratis CLI brings event, observer, projection, and read-model inspection to the terminal
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 |
Chronicle's boundary is a set of language-agnostic gRPC/protobuf contracts — any language with a gRPC implementation can talk to the kernel.
| Language | Package | Repository |
|---|---|---|
| .NET (C#) | Cratis.Chronicle on NuGet |
This repository |
| TypeScript / Node.js | @cratis/chronicle on npm |
Chronicle.TypeScript |
| Kotlin / Java (JVM) | io.cratis:chronicle on Maven Central |
Chronicle.Kotlin |
| Elixir | cratis_chronicle on Hex |
Chronicle.Elixir |
| Python | Coming soon (pre-alpha, not yet published) | Chronicle.Python |
Building a client for another language? The building a client guide distills everything the existing clients learned along the way.
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-development
ports:
- "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.Chroniclevar builder = WebApplication.CreateBuilder(args)
.AddCratisChronicle(options => options.EventStore = "MyApp");
var app = builder.Build();
app.UseCratisChronicle();
app.Run();[EventType]
public record UserOnboarded(string Name, string Email);
[EventType]
public record BookAddedToInventory(string Title, string Author, string ISBN);// Inject IEventLog or grab it from the event store
await eventLog.Append(Guid.NewGuid(), new UserOnboarded("Jane Doe", "jane@example.com"));
await eventLog.Append(Guid.NewGuid(), new BookAddedToInventory("Domain-Driven Design", "Eric Evans", "978-0321125217"));public class UserNotifier : IReactor
{
public async Task Onboarded(UserOnboarded @event, EventContext context)
{
// send welcome email, provision resources, etc.
Console.WriteLine($"Welcome, {@event.Name}!");
}
}public class BooksReducer : IReducerFor<Book>
{
public Task<Book> Added(BookAddedToInventory @event, Book? current, EventContext context) =>
Task.FromResult(new Book(
Guid.Parse(context.EventSourceId),
@event.Title,
@event.Author,
@event.ISBN));
}public class BorrowedBooksProjection : IProjectionFor<BorrowedBook>
{
public void Define(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 Application │
│ .NET · TypeScript · Kotlin/Java · Elixir │
│ │
│ ┌────────────────────────────────────────────────────┐ │
│ │ Events · Reactors · Reducers · Projections │ │
│ └────────────────────────────────────────────────────┘ │
│ │
│ Chronicle Client │
└─────────────────────────────┬────────────────────────────┘
│ gRPC (language-agnostic contracts)
┌─────────────────────────────┴────────────────────────────┐
│ Chronicle Kernel (Orleans-based) │
│ │
│ ┌────────────────┐ ┌────────────────┐ ┌────────────┐ │
│ │ Event Store │ │ Projection │ │ Web │ │
│ │ │ │ Engine │ │ Workbench │ │
│ └────────────────┘ └────────────────┘ └────────────┘ │
│ │
│ MongoDB · PostgreSQL · SQL Server · SQLite │
└──────────────────────────────────────────────────────────┘
Chronicle follows a client-server model:
| Component | Description |
|---|---|
| Chronicle Kernel | Server that manages event storage, observer dispatch, projection processing, and querying — built on Microsoft Orleans for distributed, stateful processing |
| Client SDK | .NET libraries (Cratis.Chronicle / Cratis.Chronicle.AspNetCore) that connect your app to the Kernel; TypeScript, Kotlin/Java, and Elixir clients speak the same gRPC contracts |
| Pluggable storage | MongoDB (default), PostgreSQL, SQL Server, SQLite, and in-memory providers for the event store and read models |
| Web Workbench | Browser-based dashboard available at https://localhost:35000 when running the development image |
Full documentation is available at https://www.cratis.io/chronicle/.
| Section | Description |
|---|---|
| Get Started | Quick-start guides for Console, Worker Service, and ASP.NET Core |
| Concepts | Events, projections, reactors, reducers, constraints, and more |
| Architecture | How the kernel, clients, storage, and read models fit together |
| Hosting | Production and development deployment options |
| Building a Client | Implement the gRPC contract in a new language |
| How Chronicle compares | Version-pinned, source-cited comparison of event sourcing options for .NET |
| Contributing | How to build and contribute to Chronicle |
This project is part of Cratis — free, MIT-licensed tools for building event-sourced and CQRS applications.
- Chronicle — event-sourcing database and runtime. Orleans-based kernel, pluggable storage (MongoDB default; PostgreSQL, SQL Server, SQLite, in-memory), language-agnostic gRPC contracts. Docs
- Chronicle clients — first-class .NET SDK, plus TypeScript, Kotlin/Java, and Elixir; Python coming soon (pre-alpha). AI agents connect through the Chronicle MCP server.
- Arc — opinionated CQRS framework for ASP.NET Core with commands, queries, validation, authorization, and TypeScript proxy generation. Works without event sourcing. Docs
- Components — React components aligned with Arc patterns. Docs
- CLI + Workbench — inspect and diagnose Chronicle from the terminal or the browser. Docs
- Model-first layer (experimental) — Studio, Screenplay, Stage, Scene, Prologue
- Supporting — Fundamentals, Specifications, Synopsis, Lens, Narrator, and free AI tooling (preview); Ensemble coming soon (pre-release)
- Samples — runnable event sourcing and CQRS samples for the whole stack
Everything Cratis publishes today is MIT licensed and free to use.
Blog: blog.cratis.io
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 ❤️
Release notes and announcements: the Cratis blog.