Skip to content
CratisPublic

About

Open-source (MIT) event sourcing database and processing runtime — Orleans-based kernel, pluggable storage (MongoDB, PostgreSQL, SQL Server, SQLite), and language-agnostic gRPC clients for .NET, TypeScript, Kotlin/Java, and Elixir (Python coming soon).

Topics

Resources

Code of conduct

Contributing

Security policy

Stars

65 stars

Watchers

4 watching

Forks

Latest commit

 

History

27,569 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Cratis Chronicle

Cratis Chronicle

Cratis Chronicle is an open-source (MIT) event-sourcing database and runtime for applications that need a history of meaningful changes. Record application changes as events, build queryable views with declarative projections, and react to events from .NET, TypeScript, Kotlin/Java, or Elixir.
Explore the docs »

View Samples  ·  Report a Bug  ·  Request a Feature  ·  Join the Discord

Discord NuGet Docker C# Build Publish Documentation site


📑 Table of Contents


📖 About

Cratis Chronicle is an event-sourcing database and processing runtime for applications that need to retain meaningful changes, not just current state. You append facts such as OrderPlaced to an event log. That history lets you inspect how an order changed and build new views from the events your application recorded.

Chronicle's declarative projections map events onto read models, views shaped for the queries your application serves. The kernel handles processing and storage updates. Reactors run your code when events arrive, for example to send a notification. Materialized views update after the append, so choose the consistency behavior your workflow needs.

For personal data, Chronicle encrypts fields marked as personally identifiable information (PII) under a subject's key and supports erasing that key without removing the event's position in the log. These mechanisms support your compliance work; they do not make an application compliant by themselves. Read Compliance before recording personal data.

The Orleans-based .NET kernel has a first-class .NET SDK and additional TypeScript, Kotlin/Java (JVM), and Elixir clients; a Python client is coming soon. Storage providers include MongoDB (default), PostgreSQL, SQL Server, SQLite, and in-memory implementations. Client and provider capabilities differ, so use the guide for your chosen setup. Chronicle and its bundled web workbench run without Studio, Arc, or Components. Chronicle is free to use and MIT licensed; free AI skills are also available for working with the code and documentation.

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 bundled browser tool for browsing events, inspecting observer state, and trying supported projection mappings
  • ⌨️ CLI — the Cratis CLI brings event, observer, projection, and read-model inspection to the terminal

Workbench and CLI inspection access does not grant permission to mutate data. See the workbench guide for the inspection and authorization boundaries.

For core values and principles, read our core values and principles.


✨ Key Features

🧱 Event Sourcing Foundation

Immutable Event Store Appends retain recorded facts; corrections use explicit revision or redaction operations
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

⚡ Real-time Processing

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

🔒 Data Integrity & Compliance

Multi-tenancy First-class namespace support for isolated tenant data
Constraints Server-side integrity rules enforced at append time
Compliance PII field encryption, subject-key erasure, and event redaction support personal-data handling alongside the event history
Revision Built-in support for correcting past events

💻 Developer Experience

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

🌍 Clients

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 (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.


🚀 Getting Started

Start the local kernel below, then follow a client or host quickstart to connect an application and append an event. The C# snippets here show the API shape; they are not a complete application. Use the library tutorial if you want to build the model one step at a time.

Prerequisites

Installation

Note: The latest-development Chronicle 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 127.0.0.1:35000:35000 \
  cratis/chronicle:latest-development

Option 2 — Docker Compose:

services:
  chronicle:
    image: cratis/chronicle:latest-development
    ports:
      - "127.0.0.1:35000:35000"   # gRPC, REST API and Web Workbench (single TLS port)

Both options publish the port on this machine only. The development image's workbench accepts well-known development credentials, so don't expose it on a shared network. Open the workbench at https://localhost:35000 and accept the self-signed development certificate. MongoDB stays inside the container with this setup; use the two-port quickstart if your application will query MongoDB directly.

docker compose up -d

Add the NuGet package to your .NET project:

# ASP.NET Core
dotnet add package Cratis.Chronicle.AspNetCore

# Console / Worker Service
dotnet add package Cratis.Chronicle

Quick Example

ASP.NET Core setup (Program.cs)

var builder = WebApplication.CreateBuilder(args)
    .AddCratisChronicle(options => options.EventStore = "MyApp");

var app = builder.Build();
app.UseCratisChronicle();
app.Run();

Define events

[EventType]
public record UserOnboarded(string Name, string Email);

[EventType]
public record BookAddedToInventory(string Title, string Author, string ISBN);

Append events

// 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"));

React to events (Reactor)

public class UserNotifier : IReactor
{
    public async Task Onboarded(UserOnboarded @event, EventContext context)
    {
        // send welcome email, provision resources, etc.
        Console.WriteLine($"Welcome, {@event.Name}!");
    }
}

Build read models (Reducer)

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));
}

Declarative projections

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.


📐 Architecture

┌──────────────────────────────────────────────────────────┐
│                     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

📚 Documentation

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

🧩 The Cratis ecosystem

This project is part of Cratis Platform — tools for building event-sourced and CQRS applications.

Chronicle is MIT licensed and free to use.

Blog: blog.cratis.io


🤝 Contributing

Contributions are what make the open-source community an amazing place to learn, inspire, and create. Any contribution you make is greatly appreciated!

  1. Fork the repository
  2. Create a feature branch: git checkout -b feature/AmazingFeature
  3. Commit your changes: git commit -m 'Add some AmazingFeature'
  4. Push to the branch: git push origin feature/AmazingFeature
  5. 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: Open in VSCode


💬 Support

Channel Details
💬 Discord Join the community on Discord for questions and discussions
🐛 GitHub Issues Report bugs or request features

📊 Repository Stats

Repobeats analytics


📄 License

Distributed under the MIT License. See LICENSE for full details.


🙏 Acknowledgements

Release notes and announcements: the Cratis blog.

About

Open-source (MIT) event sourcing database and processing runtime — Orleans-based kernel, pluggable storage (MongoDB, PostgreSQL, SQL Server, SQLite), and language-agnostic gRPC clients for .NET, TypeScript, Kotlin/Java, and Elixir (Python coming soon).

Topics

Resources

Code of conduct

Contributing

Security policy

Stars

65 stars

Watchers

4 watching

Forks

Releases

Packages

Used by

Contributors

Languages