Event sourcing in Elixir
Chronicle is an open-source (MIT) event-sourcing database and processing runtime, and cratis_chronicle is its idiomatic Elixir client. It exposes OTP-native constructs — use Chronicle.EventType, use Chronicle.ReadModel, use Chronicle.Reactor, use Chronicle.Reducer, and use Chronicle.Seeder — plus model-bound constraints, context-aware appends with process-scoped identity, correlation, and causation metadata, optimistic concurrency, transactions, jobs and webhooks, and automatic reconnection with exponential backoff. The client supervises a connection to the Chronicle kernel as part of your application’s supervision tree.
With event sourcing, every state change is captured as an immutable event rather than an update in place. Chronicle stores those events, and read models are derived from them — declared model-bound projections execute server-side, or you can fold events into read models in your own process with a reducer.
The event store is not BEAM-only: Chronicle’s kernel exposes a language-agnostic gRPC/protobuf boundary, and the same store is reachable from the .NET, TypeScript, and Kotlin/Java clients as well. Storage is pluggable — MongoDB by default, with PostgreSQL, SQL Server, SQLite, and in-memory providers implemented in the kernel.
Install
Section titled “Install”defp deps do [ {:cratis_chronicle, "~> 0.0"} ]endA taste
Section titled “A taste”An event type, a supervised client, and an append — from the client repository’s quick example:
defmodule MyApp.Events.AccountOpened do use Chronicle.EventType, id: "account-opened-v1" defstruct [:account_id, :owner_name, :initial_balance]end
defmodule MyApp.Application do use Application
def start(_type, _args) do children = [ {Chronicle.Client, connection_string: "chronicle://localhost:35000", event_store: "my-app", otp_app: :my_app} ]
Supervisor.start_link(children, strategy: :one_for_one) endend
# Append an event:ok = Chronicle.append("account-42", %MyApp.Events.AccountOpened{ account_id: "account-42", owner_name: "Alice", initial_balance: 1000})For a local kernel to append to, the development Docker image is the quickest path: docker run -p 35000:35000 cratis/chronicle:latest-development.
Where to go next
Section titled “Where to go next”Looking for another language? See Chronicle in your language for the .NET, TypeScript, and Kotlin/Java clients.