Skip to content

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.

mix.exs
defp deps do
[
{:cratis_chronicle, "~> 0.0"}
]
end

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)
end
end
# 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.

Looking for another language? See Chronicle in your language for the .NET, TypeScript, and Kotlin/Java clients.