Skip to content

Event sourcing in Go

Chronicle is an open-source (MIT) event-sourcing database and processing runtime, and github.com/cratis/chronicle.go is its Go client. You register typed events, connect over TLS, select an event store and namespace, and append with explicit concurrency protection and complete outcomes. The client is an experimental foundation, v0.x: it covers the write side and event history reads, and not yet observers, projections, or automatic lifecycle recovery.

With event sourcing, your application appends immutable facts and derives every view from them, instead of overwriting state in place. Chronicle stores those events and enforces constraints on the server. The event store is not Go-specific: its kernel exposes a language-agnostic gRPC/protobuf boundary, so the same store is reachable from the .NET, TypeScript, Kotlin/Java, and Elixir clients too.

AreaStatus per the README
Connection, TLS, OAuth, and compatibility checksImplemented
Typed event registrationImplemented
Single and atomic batch appends, with explicit concurrency controlImplemented
Event history readsImplemented
Observers and projectionsNot yet implemented
Automatic lifecycle recoveryNot yet implemented

Contracts are pinned to Chronicle 19.32.3, and the generated contracts are public packages in the same Go module, so you need no .NET checkout. If you read the client docs, check each page against the parity page: some documentation describes partial work beyond the README’s summary, such as runtime projection registration.

The client requires Go 1.26 or later. The latest released tag checked on 2026-10-20 is v0.11.0. Install that version with:

Terminal window
go get github.com/cratis/chronicle.go@v0.11.0

Check the Go package page for what has been published before you depend on it.

Start the development kernel and wait for https://localhost:35000/health to report Healthy:

Terminal window
docker run --rm --name chronicle-go -p 35000:35000 cratis/chronicle:19.32.3-development

This program, from the client repository’s quick start, registers an event, connects, and appends it:

package main
import (
"context"
"errors"
"fmt"
"log"
"time"
chronicle "github.com/cratis/chronicle.go"
"github.com/cratis/chronicle.go/events"
)
type CustomerRegistered struct {
Name string `json:"name"`
}
func main() {
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
defer cancel()
if err := appendCustomer(ctx); err != nil {
log.Fatal(err)
}
}
func appendCustomer(ctx context.Context) (err error) {
registry := chronicle.NewRegistry()
if _, err = chronicle.RegisterEvent[CustomerRegistered](registry,
events.WithID("customer-registered")); err != nil {
return err
}
client, err := chronicle.NewClient(chronicle.WithDevelopmentDefaults(),
chronicle.WithRegistry(registry))
if err != nil {
return err
}
defer func() { err = errors.Join(err, client.Close()) }()
store, err := client.EventStore(ctx, "customers")
if err != nil {
return err
}
result, err := store.EventLog().Append(ctx, "customer-42", CustomerRegistered{Name: "Ada"})
if err != nil {
return err
}
if err = result.Err(); err != nil {
return err
}
fmt.Printf("Appended event at position %d\n", *result.Position)
return nil
}

WithDevelopmentDefaults explicitly permits the kernel’s self-signed certificate. Production TLS validates by default, so configure real roots and credentials. Two limits from the README matter on the first day:

  • An append transport error may hide a committed event, so never retry blindly.
  • Default optimistic concurrency leaves empty history unchecked. Use NoMatchingEvent when the first append must be protected.

Arc is Cratis’s CQRS application framework, and Arc.Go is its Go counterpart (github.com/cratis/arc.go). Its README states early development: foundation packages, HTTP hosting, and model-bound command and query pipelines exist, with experimental TypeScript proxy generation and optional Chronicle integration. The latest released root-module tag checked on 2026-10-20 is v0.1.1; the API remains experimental. Install it with go get github.com/cratis/arc.go@v0.1.1. A root-module tag does not release its separate integration or tools modules. The Arc.Go parity ledger lists the Partial areas and limits.

For shared Go building blocks, Fundamentals.Go is released as v0.3.2, checked on the same date. Install it with go get github.com/cratis/fundamentals.go@v0.3.2; see Fundamentals for Go.

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