From aa5d936c76dfc6759814c0f310be29fe13e22a18 Mon Sep 17 00:00:00 2001 From: woksin Date: Sun, 30 Aug 2026 22:11:10 +0200 Subject: [PATCH] Refine event sourcing comparison pages Give KurrentDB, Critter Stack, and Axon their documented strengths while presenting Cratis as a different ecosystem choice rather than a universal winner. --- .../docs/compare-event-sourcing-dotnet.mdx | 128 ++++++++--------- .../docs/compare-event-sourcing-jvm.mdx | 130 ++++++++---------- 2 files changed, 115 insertions(+), 143 deletions(-) diff --git a/web/src/content/docs/compare-event-sourcing-dotnet.mdx b/web/src/content/docs/compare-event-sourcing-dotnet.mdx index 1d9e36a..465b416 100644 --- a/web/src/content/docs/compare-event-sourcing-dotnet.mdx +++ b/web/src/content/docs/compare-event-sourcing-dotnet.mdx @@ -1,104 +1,92 @@ --- -title: "Event sourcing in .NET: comparing KurrentDB, Marten, and Cratis Chronicle" -description: "A version-pinned, source-cited comparison of event sourcing options for .NET — KurrentDB (formerly EventStoreDB) 26.0, Marten 9.30.0, and Cratis Chronicle 17.0.0 — covering license, storage model, language clients, subscriptions, projections, hosting, and each tool's wider ecosystem and supporting products, with citations and retrieval dates for every row." -head: - - tag: meta - attrs: - name: keywords - content: "event sourcing .NET comparison, event sourcing C#, .NET event store comparison, KurrentDB vs Marten vs Cratis Chronicle, Marten vs Cratis Chronicle, EventStoreDB alternatives, KurrentDB alternatives, choosing an event sourcing framework for .NET, event sourcing database .NET" +title: "Event sourcing in .NET: KurrentDB, Marten, and Cratis Chronicle" +description: "Compare KurrentDB 26.0, Marten 9.30.0, and Cratis Chronicle 16.42.0 for .NET event sourcing, with versioned sources and architectural trade-offs." --- import { Aside } from '@astrojs/starlight/components'; -Choosing an event sourcing foundation for a .NET system is a long-lived decision. The event store outlives frameworks, UI rewrites, and often the team that chose it. Yet most comparisons available today reduce to popularity: the tools with the most blog posts win the evaluation before it starts. +KurrentDB, Marten, and Cratis Chronicle all support event-sourced systems, but they make different architectural choices. KurrentDB is a dedicated event database, Marten is an in-process .NET library built on PostgreSQL, and Chronicle is a separate event-sourcing server and processing runtime. -This comparison takes a different approach. Every factual row names the exact versions compared and is reproducible from public documentation and released packages. Where our own product appears, the same rules apply — including the limitations. +This page compares the capabilities where those products overlap. It does not rank them, and it does not compare the complete Critter Stack with the wider Cratis ecosystem. -## The candidates +## What is being compared -- **KurrentDB (formerly EventStoreDB)** — a purpose-built event store database with clients for multiple languages. You bring your own CQRS layer and read-model infrastructure. -- **Marten** — a .NET library that turns PostgreSQL into a document and event store. Deep .NET integration; PostgreSQL is a prerequisite; .NET is the boundary. -- **Cratis Chronicle** — an event-sourcing database and processing runtime with a first-class .NET SDK and released TypeScript, Java/Kotlin (JVM), and Elixir client packages. Pairs with [Arc](/arc/) (an opinionated CQRS application framework for ASP.NET Core with TypeScript proxy generation) and a [React component library](/components/). +- **KurrentDB (formerly EventStoreDB)** — a purpose-built event database with official clients for several languages, server-managed persistent subscriptions, projections, and connectors. +- **Marten** — a transactional document database and event store for .NET applications using PostgreSQL, with inline, asynchronous, and live projection models. +- **Cratis Chronicle** — an event-sourcing database and processing runtime with a separate server, multiple storage providers, and released clients for .NET, TypeScript, Kotlin/Java, and Elixir. -## How this comparison is made +Marten is also part of the [Critter Stack](https://jasperfx.net). [Wolverine](https://wolverinefx.net) is its messaging and web-development framework, with documented transport support, failure policies, and persistent inbox/outbox messaging. Polecat brings the event-store and document-database model to SQL Server, while Fisher targets SQLite. Chronicle belongs to the wider Cratis ecosystem, where [Arc](/arc/), [Components](/components/), the [Cratis CLI](/cli/), and Workbench cover adjacent application and operating concerns. These are separate products in their respective families, not features attributed to Marten or Chronicle itself. + +## Method and versions -## Compared versions - -All facts retrieved **2026-08-28** unless a row states otherwise. - | Tool | Compared version | Version source | -| ---- | ---------------- | -------------- | -| KurrentDB (formerly EventStoreDB) | Server 26.0 documentation series; 26.0.3 is the release named in the official installation documentation | [docs.kurrent.io/server/v26.0/quick-start/installation.html](https://docs.kurrent.io/server/v26.0/quick-start/installation.html) (retrieved 2026-08-28) | -| Marten | 9.30.0 (latest stable package on NuGet at retrieval) | [nuget.org listing for `Marten`](https://www.nuget.org/packages/Marten) (retrieved 2026-08-28) | -| Cratis Chronicle | 17.0.0 (latest stable `Cratis.Chronicle` package on NuGet at retrieval); server distributed as the `cratis/chronicle` Docker image | [nuget.org listing for `Cratis.Chronicle`](https://www.nuget.org/packages/Cratis.Chronicle); [hub.docker.com/r/cratis/chronicle](https://hub.docker.com/r/cratis/chronicle) (retrieved 2026-08-28) | - -## The comparison matrix +| --- | --- | --- | +| KurrentDB | Server 26.0 documentation series; 26.0.3 is the release named by the installation documentation | [KurrentDB 26.0 installation documentation](https://docs.kurrent.io/server/v26.0/quick-start/installation.html) | +| Marten | 9.30.0 | [Marten 9.30.0 on NuGet](https://www.nuget.org/packages/Marten/9.30.0) | +| Cratis Chronicle | Server and .NET client 16.42.0; server distributed as the `cratis/chronicle` Docker image | [Cratis.Chronicle 16.42.0 on NuGet](https://www.nuget.org/packages/Cratis.Chronicle/16.42.0), [Chronicle Docker tags](https://hub.docker.com/r/cratis/chronicle/tags) | -| Row | KurrentDB (server 26.0) | Marten (9.30.0) | Cratis Chronicle (17.0.0) | -| --- | ----------------------- | --------------- | ------------------------- | -| License | Kurrent License v1 (KLv1). The KurrentDB documentation states the source code is available to view and that KLv1 "is not an OSI-approved Open Source License"; enterprise features are enabled with a license key. | MIT License. | MIT License. | -| Storage model | Purpose-built, event-native database; events are stored in streams inside KurrentDB's own storage engine. | Library that uses PostgreSQL as the underlying data store, using its JSON support and ACID compliance; PostgreSQL is a prerequisite. | Event-sourcing database with pluggable storage-provider implementations documented in the [repository README](https://github.com/Cratis/Chronicle/blob/main/README.md): MongoDB (default), PostgreSQL, SQL Server, and SQLite, plus an in-memory provider. | -| Language clients | Official gRPC client SDKs listed for Python, Node.js (JavaScript/TypeScript), Java, .NET, Go, and Rust; community clients listed for Ruby, Elixir, and PHP; an HTTP interface also exists (AtomPub-based application API disabled by default and planned for removal). | .NET library; runs inside a .NET application process. | First-class .NET client SDK (`Cratis.Chronicle` on NuGet). Released client packages also on public registries: `@cratis/chronicle` 3.1.0 on npm (MIT), `io.cratis:chronicle` 2.10.0 on Maven Central, `cratis_chronicle` 2.2.0 on Hex (MIT). A Python client is coming soon: no package is published on PyPI as of the retrieval date, and no commitment is implied. | -| Subscriptions / event processing | Catch-up subscriptions (client keeps position) and persistent subscriptions (server keeps position, competing-consumers pattern, at-least-once delivery across consumer groups). | Subscription model (`ISubscription`, documented since 7.7) running in Marten's async daemon subsystem as a background process inside the application, for pushing captured events into custom processing. | Reactors (react to events as they occur), Reducers (imperatively transform events into typed read models), and Observers (low-level event subscriptions with guaranteed delivery), as documented in the [repository README](https://github.com/Cratis/Chronicle/blob/main/README.md). | -| Projections / read models | Server-side projections subsystem: built-in (system) projections and user-defined JavaScript projections; projections require the event body to be JSON. The docs note many read-model problems are better served by a separate read model populated by a catch-up subscription. | Rich projection support for read-side views: inline projections (in the capture transaction), async projections (background, eventually consistent), and live projections (evaluated on demand). | Declarative, fluent projection builders with join, set, and remove support, producing typed read models, as documented in the [repository README](https://github.com/Cratis/Chronicle/blob/main/README.md). | -| Hosting model | Separate database server process: single node or a highly-available cluster (three nodes for cluster deployment); installable from Linux package repositories, on Windows, or via Docker images; some features require a license key. | In-process library: embedded in the host .NET application; background projection/subscription work runs in the async daemon inside the application. Requires a PostgreSQL database. | Separate server (Chronicle Kernel) run via the `cratis/chronicle` Docker image, exposing gRPC, REST API, and the Web Workbench management dashboard on a single port; the `latest-development` image bundles MongoDB for local development. | +## Core comparison -### Row sources +| Question | KurrentDB 26.0 | Marten 9.30.0 | Cratis Chronicle 16.42.0 | +| --- | --- | --- | --- | +| What is the product boundary? | A separate event-native database server with an integrated streaming engine. | A .NET library providing a transactional document database and event store inside the application. | A separate event-sourcing server and processing runtime used through client SDKs. | +| Where are events stored? | In streams managed by KurrentDB's storage engine. | Marten stores events and documents in PostgreSQL. Within the wider Critter Stack, the separate Polecat and Fisher products target SQL Server and SQLite respectively. | Through pluggable providers documented for MongoDB (default), PostgreSQL, SQL Server, SQLite, and in-memory use. | +| What is the language boundary? | Official gRPC clients are listed for Python, Node.js, Java, .NET, Go, and Rust, with additional community clients. | The event-store and document-database APIs are .NET libraries running in the host application. | A first-class .NET SDK, plus released TypeScript 3.1.1, Kotlin/Java 2.10.0, and Elixir 2.2.0 clients. The Python client is not yet published. | +| How are events consumed? | Catch-up subscriptions keep position in the client. Persistent subscriptions keep position on the server and support consumer groups, acknowledgements, retries, parked events, and replay. KurrentDB documents at-least-once delivery and explicitly notes that persistent-subscription ordering is not guaranteed. | Marten subscriptions run through the asynchronous daemon inside the application and pass captured events to application-defined processing. | Reactors handle event-driven application work, Reducers derive typed read models, and Observers provide low-level event subscriptions. | +| How are read models produced? | Built-in and user-defined JavaScript projections can react to events and emit or link events. KurrentDB notes that many read-model workloads are better handled by a separate read model fed by a catch-up subscription. | Inline projections run in the event-capture transaction, asynchronous projections run in the daemon, and live projections are evaluated on demand. | Reducers and declarative projection builders produce typed read models, including documented set, join, and remove operations. | +| How can events reach other systems? | Server-side Connectors use catch-up subscriptions to filter or transform events and send them to documented sinks including HTTP, Kafka, RabbitMQ, MongoDB, Elasticsearch, and Serilog. | Marten subscriptions hand events to custom .NET processing. Wolverine is the Critter Stack's separate messaging and web framework, with documented transports, failure policies, asynchronous processing, and persistent inbox/outbox messaging. | Client APIs expose the server over gRPC and REST, while Reactors provide application-defined event processing. | +| What runs in production? | A separate KurrentDB server, as a single node or documented cluster topology. Some features require a license key. | The Marten library and asynchronous daemon run in the .NET application, backed by PostgreSQL. | The Chronicle Kernel runs as a separate Docker-hosted server and exposes gRPC, REST, and the bundled Workbench browser surface. | +| What is the license boundary? | Kurrent License v1; KurrentDB states that it is not an OSI-approved open-source license. Some enterprise features require a license key. | MIT License. | MIT License for Chronicle and its bundled local Workbench. Other Cratis products retain their own license and release boundaries. | -All retrieved 2026-08-28: +## Where each option fits -- **KurrentDB** — license, client list, protocols: [docs.kurrent.io/server/v26.0/quick-start/](https://docs.kurrent.io/server/v26.0/quick-start/) (Introduction); hosting, packages, Docker, license keys, 26.0.3: [docs.kurrent.io/server/v26.0/quick-start/installation.html](https://docs.kurrent.io/server/v26.0/quick-start/installation.html); projections: [docs.kurrent.io/server/v26.0/features/projections/](https://docs.kurrent.io/server/v26.0/features/projections/); persistent subscriptions: [docs.kurrent.io/server/v26.0/features/persistent-subscriptions.html](https://docs.kurrent.io/server/v26.0/features/persistent-subscriptions.html). -- **Marten** — positioning, PostgreSQL store: [martendb.io](https://martendb.io) (home) and [martendb.io/events/](https://martendb.io/events/); projection types: [martendb.io/events/](https://martendb.io/events/) (terminology: inline/async/live projections); subscriptions: [martendb.io/events/subscriptions](https://martendb.io/events/subscriptions); license: [github.com/JasperFx/marten `LICENSE`](https://github.com/JasperFx/marten/blob/master/LICENSE) (MIT); version: [nuget.org listing for `Marten`](https://www.nuget.org/packages/Marten) (9.30.0). -- **Cratis Chronicle** — identity, kernel/SDK/Workbench/storage providers (MongoDB default; PostgreSQL, SQL Server, SQLite, in-memory), reactors/reducers/projections/observers, Docker hosting: [github.com/Cratis/Chronicle `README.md`](https://github.com/Cratis/Chronicle/blob/main/README.md); license: [github.com/Cratis/Chronicle `LICENSE`](https://github.com/Cratis/Chronicle/blob/main/LICENSE) (MIT); versions and client packages: [nuget.org](https://www.nuget.org/packages/Cratis.Chronicle) (`Cratis.Chronicle` 17.0.0), [npm](https://www.npmjs.com/package/@cratis/chronicle) (`@cratis/chronicle` 3.1.0), [Maven Central](https://central.sonatype.com/artifact/io.cratis/chronicle) (`io.cratis:chronicle` 2.10.0), [hex.pm](https://hex.pm/packages/cratis_chronicle) (`cratis_chronicle` 2.2.0), [pypi.org](https://pypi.org) (no `cratis-chronicle` package published), [hub.docker.com/r/cratis/chronicle](https://hub.docker.com/r/cratis/chronicle). +These are not quality rankings. They identify the architectural choice each product makes most explicit. -## Ecosystem and supporting products +### KurrentDB -An event store rarely ships alone. Each of the compared tools names its own supporting products; the same method applies here — every cell restates the named vendor's own public listing or documentation, with retrieval dates, and implies nothing about quality, integration depth, or superiority. +Examine KurrentDB closely when you want the event store to be dedicated infrastructure, need official clients across several languages, or want server-managed persistent subscriptions and connectors while keeping the application architecture in your own code. -| Row | KurrentDB (server 26.0) | Marten (9.30.0) | Cratis Chronicle (17.0.0) | -| --- | ----------------------- | --------------- | ------------------------- | -| Wider product family | Official gRPC client SDKs for six languages plus community clients (see the Language clients row); the documented server feature set includes projections, persistent subscriptions, and a Connectors subsystem (next row). | Listed by JasperFx as part of the "Critter Stack", described as "one family of .NET tools for event sourcing, document storage, and messaging": Wolverine (messaging), Polecat (SQL Server), Fisher (SQLite), Weasel (schema), Alba (integration testing), and CritterWatch (monitoring). | Part of the Cratis ecosystem: [Arc](/arc/) (an opinionated CQRS application framework for ASP.NET Core with commands, queries, validation, authorization, and TypeScript proxy generation), [Components](/components/) (a React component library aligned with Arc application patterns), the [Cratis CLI](/cli/) (terminal workflows for inspecting and diagnosing Chronicle), and the Web Workbench management dashboard exposed by the server. Released language clients for .NET, TypeScript, JVM, and Elixir (see the Language clients row). | -| Pushing events to other systems | Server-side Connectors subsystem, documented as pre-installed and enabled by default: each connector runs a catch-up subscription that can filter or transform events and push them to an external system via a sink; the documented sink catalog lists Elasticsearch, HTTP, Kafka, MongoDB, RabbitMQ, and Serilog sinks. | Subscriptions running in the async daemon push captured events into custom processing (see the Subscriptions row); messaging integration is positioned in the wider Critter Stack through Wolverine. | The server exposes gRPC and REST APIs (see the Hosting model row); Reactors provide documented event-driven processing, and Arc's TypeScript proxy generation carries contracts to the frontend. | -| AI assistance | No entry compiled for this row; per the caveats, absence means only that it was not found in the sources cited for this page. | The JasperFx site describes its libraries as "optimized for low-friction development, testability, and AI-assisted workflows" and references its AI skills in current posts. | Cratis documents free AI skills, rules, and diagnostics for AI-assisted development on the [AI page](/ai/); current availability and distribution status are stated on that page. | +### Marten and the Critter Stack -### Ecosystem row sources +Examine Marten closely when your application is .NET, PostgreSQL is already an accepted dependency, and you want document storage, event storage, and several projection modes in the same application and database transaction boundary. The broader Critter Stack is not limited to that Marten/PostgreSQL profile: Polecat targets SQL Server, Fisher targets SQLite, and Wolverine provides the family's messaging and web-development model. Evaluate those products together when database choice, durable messaging, HTTP handling, testing, schema management, or monitoring are part of the decision. -All retrieved 2026-08-28: +### Cratis Chronicle and the Cratis ecosystem -- **KurrentDB** — Connectors overview (pre-installed, enabled by default, catch-up subscription, filter/transform, sinks): [docs.kurrent.io/server/v26.0/features/connectors/](https://docs.kurrent.io/server/v26.0/features/connectors/); sink catalog: [docs.kurrent.io/server/v26.0/features/connectors/sinks/](https://docs.kurrent.io/server/v26.0/features/connectors/sinks/). -- **Marten / Critter Stack** — family listing and wording ("one family of .NET tools for event sourcing, document storage, and messaging"; Wolverine, Polecat, Fisher, Weasel, Alba, CritterWatch; "AI-assisted workflows"): [jasperfx.net](https://jasperfx.net); Wolverine documentation: [wolverinefx.net](https://wolverinefx.net). -- **Cratis Chronicle** — Arc: [cratis.io/arc/](https://cratis.io/arc/); Components: [cratis.io/components/](https://cratis.io/components/); CLI: [cratis.io/cli/](https://cratis.io/cli/); Workbench: [github.com/Cratis/Chronicle `README.md`](https://github.com/Cratis/Chronicle/blob/main/README.md); AI skills, rules, and diagnostics: [cratis.io/ai/](https://cratis.io/ai/); client packages: registry listings cited under Row sources above. +Examine Chronicle closely when you want event storage and event processing behind a separate runtime, need a choice among its documented storage providers, or want several language clients to use the same server contracts. The wider Cratis experience connects Chronicle to Arc's CQRS application model, generated TypeScript contracts, React components, CLI workflows, and Workbench. That coherence is a different product boundary, not evidence that the other approaches are incomplete. -## Caveats and limitations +## Questions to answer before choosing -- **This matrix compares documentation, not behavior.** Every cell restates what the named tool's own public documentation or registry listing says at the named version and retrieval date. It does not test, measure, or rank anything, and absence of a capability from a cell means only that it was not found in the cited source — not that the tool lacks it. -- **Client existence is not client parity.** A listed client package says nothing about feature coverage relative to the primary client — for any tool in this table, including Chronicle. -- **An ecosystem listing is not an integration or quality claim.** The ecosystem rows restate each vendor's own product-family listing at the retrieval date. They say nothing about how well the pieces work together, how complete any supporting product is, or how the families compare — and an empty or missing entry means only that nothing was found in the cited sources. -- **Chronicle's storage-provider row restates the repository README's own listing.** The [repository README](https://github.com/Cratis/Chronicle/blob/main/README.md) documents pluggable storage with MongoDB (default), PostgreSQL, SQL Server, SQLite, and in-memory providers; the row sticks to that cited wording and implies nothing about provider parity or completeness. -- **The Python client is strictly coming soon.** Pre-alpha, unpublished, and no commitment implied. -- **KurrentDB licensing nuance.** The license row quotes KurrentDB's own documentation; read KLv1 yourself for terms. This page draws no conclusion about fitness of any license for any use. -- **Versions move.** Each compared tool releases on its own cadence; every cell is pinned to the versions and retrieval dates above and may be stale the day after retrieval. +1. **Process boundary:** Should event storage and processing run inside the application or behind a separate server? +2. **Database boundary:** Do you want PostgreSQL as the fixed foundation, a purpose-built storage engine, or a runtime with documented provider choices? +3. **Application model:** Do you want to assemble the CQRS and messaging layers yourself, adopt the Critter Stack's .NET model, or use the wider Cratis application path? +4. **Projection model:** Which work must share the append transaction, and which work may run asynchronously or on demand? +5. **Language boundary:** Is .NET the complete application boundary, or must several language clients use the same event server? +6. **Operations:** How will your team inspect subscription progress, failed processing, parked work, projections, replay, and recovery for the exact topology you deploy? +7. **Commercial and license boundary:** Which server features, support terms, and licenses apply to the exact products you intend to run? -## How to choose +## Limitations -Rather than a winner, use fit questions: +- This is a documentation comparison, not a benchmark or production evaluation. +- The products do not have identical boundaries, so an empty cell would not prove that a wider product family lacks a capability. +- Client availability does not establish client parity. +- Storage-provider availability does not establish provider parity. +- Product-family membership does not establish integration depth, common maturity, compatibility, support, or one commercial boundary. +- Versions and documentation change independently; verify the cited sources against the release you plan to adopt. -- **Do you want a dedicated event database and your own application layer?** A purpose-built store with bring-your-own CQRS gives maximum control and maximum assembly work. -- **Are you a PostgreSQL shop wanting minimum new infrastructure?** A library-on-PostgreSQL approach is hard to beat for operational simplicity. -- **Do you want event sourcing, CQRS, and frontend integration designed together?** An integrated platform trades some flexibility for coherence: projections, read models, generated frontend contracts, and query updates that share one design. -- **Is your organization polyglot?** Check which client languages are first-party and what each client actually supports — client existence is not client parity, for any tool including ours. -- **Who explains the system at 3 a.m.?** Compare the operational surfaces: what does each tool show you about observer progress, failed projections, and replay? +## Sources -## What we deliberately did not claim +Sources checked 2026-08-30: -This comparison states released, verifiable facts. It does not claim any tool is faster, more scalable, more reliable, or more production-proven than another — those claims require benchmarks and evidence this page does not carry. Where a capability is listed for Chronicle, it comes from the named released version; the same courtesy is extended to every tool compared, from that tool's own documentation. +- **KurrentDB:** [introduction and clients](https://docs.kurrent.io/server/v26.0/quick-start/), [installation](https://docs.kurrent.io/server/v26.0/quick-start/installation.html), [persistent subscriptions](https://docs.kurrent.io/server/v26.0/features/persistent-subscriptions.html), [projections](https://docs.kurrent.io/server/v26.0/features/projections/), and [Connectors](https://docs.kurrent.io/server/v26.0/features/connectors/). +- **Marten and Critter Stack:** [Marten](https://martendb.io), [Marten event store and projections](https://martendb.io/events/), [Marten subscriptions](https://martendb.io/events/subscriptions), [Marten license](https://github.com/JasperFx/marten/blob/master/LICENSE), [Critter Stack product family](https://jasperfx.net), and [Wolverine](https://wolverinefx.net). +- **Cratis Chronicle:** [Chronicle repository and documentation](https://github.com/Cratis/Chronicle), [Chronicle license](https://github.com/Cratis/Chronicle/blob/main/LICENSE), [NuGet](https://www.nuget.org/packages/Cratis.Chronicle/16.42.0), [npm](https://www.npmjs.com/package/@cratis/chronicle/v/3.1.1), [Maven Central](https://central.sonatype.com/artifact/io.cratis/chronicle/2.10.0), [Hex](https://hex.pm/packages/cratis_chronicle/2.2.0), and [Docker Hub](https://hub.docker.com/r/cratis/chronicle/tags). -## How this page stays current +## Corrections and refresh -This matrix is re-verified — every cell checked against the then-current released versions with new retrieval dates — whenever a compared tool ships a new major or minor server/package release, a compared tool changes its license or client list, or 90 days elapse since the last recorded retrieval date. If a compared tool disputes a row and it cannot be re-verified, the row is corrected or removed. +We recheck this page when a compared product changes a relevant major or minor release, license, client list, or documented capability, and at least every 90 days. If a statement cannot be confirmed from the named product's own current public sources, we correct or remove it. -If you spot a cell that no longer matches its source, [tell us](/feedback/) — we will re-verify and fix it. +If you find a factual error or a better first-party source, [send the correction](/feedback/). diff --git a/web/src/content/docs/compare-event-sourcing-jvm.mdx b/web/src/content/docs/compare-event-sourcing-jvm.mdx index 7a1ff85..03860dd 100644 --- a/web/src/content/docs/compare-event-sourcing-jvm.mdx +++ b/web/src/content/docs/compare-event-sourcing-jvm.mdx @@ -1,107 +1,91 @@ --- -title: "Event sourcing on the JVM: comparing Axon, KurrentDB, and Cratis Chronicle" -description: "A version-pinned, source-cited comparison of event sourcing options for Kotlin and Java — Axon Framework 5.3.1 with Axon Server, KurrentDB 26.0 with the io.kurrent:kurrentdb-client 1.2.1 Java client, and Cratis Chronicle 17.0.0 with the io.cratis:chronicle 2.10.0 JVM client and its Spring Boot starter — covering license, storage model, programming model, Spring Boot integration, subscriptions, projections, hosting, and each tool's wider ecosystem, with citations and retrieval dates for every row." -head: - - tag: meta - attrs: - name: keywords - content: "event sourcing JVM comparison, event sourcing Kotlin, event sourcing Java, Axon Framework vs KurrentDB vs Cratis Chronicle, Axon Framework alternatives, event store Java comparison, Kotlin event sourcing framework, Spring Boot event sourcing, choosing an event sourcing framework for the JVM, event sourcing database Java" +title: "Event sourcing on the JVM: Axon, KurrentDB, and Cratis Chronicle" +description: "Compare Axon Framework 5.3.1, KurrentDB 26.0, and Cratis Chronicle 16.42.0 for Java and Kotlin event sourcing, with versioned sources and trade-offs." --- import { Aside } from '@astrojs/starlight/components'; -Choosing an event sourcing foundation for a JVM system is a long-lived decision. The event store outlives frameworks, UI rewrites, and often the team that chose it. Yet most comparisons available today reduce to popularity: the tools with the most blog posts win the evaluation before it starts. +Axon Framework, KurrentDB, and Cratis Chronicle all support event-sourced JVM systems, but they are not the same kind of product. Axon is an application framework with command, event, and query infrastructure plus pluggable event storage. KurrentDB and Chronicle are separate server products used through client SDKs. -This comparison takes the same approach as our [.NET comparison](/compare-event-sourcing-dotnet/): every factual row names the exact versions compared and is reproducible from public documentation and released packages. Where our own product appears, the same rules apply — including the limitations. +This page compares the concerns where those products overlap. It does not treat a database client as a complete application framework, and it does not treat framework breadth as proof that a database is missing features. -## The candidates +## What is being compared -- **Axon Framework (with Axon Server)** — a JVM framework for building applications based on Domain-Driven Design, CQRS, and event sourcing, with a pluggable event storage engine. Axon Server is its default event store and message bus, run as a separate server. -- **KurrentDB (formerly EventStoreDB) with the Java client** — a purpose-built event store database with an official gRPC Java client for JVM languages. You bring your own CQRS layer and read-model infrastructure. -- **Cratis Chronicle with the JVM client** — an event-sourcing database and processing runtime with a JVM client usable from both Kotlin and Java (`io.cratis:chronicle`), plus a Spring Boot starter that reduces setup to a dependency. The same server is reachable from the released [.NET, TypeScript, and Elixir clients](/chronicle-clients/). +- **Axon Framework with Axon Server or another storage engine** — a JVM framework for DDD, CQRS, command and query handling, event sourcing, and event processing. Axon Server is the default event store and message-routing option, while PostgreSQL and JPA storage engines are also documented. +- **KurrentDB with its Java client** — a dedicated event database with an official JVM client. Application-layer CQRS, aggregates, and read-model code remain application concerns. +- **Cratis Chronicle with its JVM client** — a separate event-sourcing server and processing runtime with Kotlin and Java APIs, artifact discovery, and an official Spring Boot starter. -## How this comparison is made +## Method and versions -## Compared versions - -All facts retrieved **2026-08-29** unless a row states otherwise. - | Tool | Compared version | Version source | -| ---- | ---------------- | -------------- | -| Axon Framework | 5.3.1 (latest release on Maven Central at retrieval); documentation cited from the 5.3 reference series. Axon Server documentation cited from its current installation documentation | [Maven Central metadata for `org.axonframework:axon-messaging`](https://repo1.maven.org/maven2/org/axonframework/axon-messaging/maven-metadata.xml); [docs.axoniq.io/axon-framework-reference/5.3/](https://docs.axoniq.io/axon-framework-reference/5.3/events/infrastructure/) (retrieved 2026-08-29) | -| KurrentDB (formerly EventStoreDB) | Server 26.0 documentation series; 26.0.3 is the release named in the official installation documentation. Java client `io.kurrent:kurrentdb-client` 1.2.1 (latest release on Maven Central at retrieval) | [docs.kurrent.io/server/v26.0/quick-start/installation.html](https://docs.kurrent.io/server/v26.0/quick-start/installation.html); [Maven Central metadata for `io.kurrent:kurrentdb-client`](https://repo1.maven.org/maven2/io/kurrent/kurrentdb-client/maven-metadata.xml) (retrieved 2026-08-29) | -| Cratis Chronicle | Server 17.0.0 (latest stable `Cratis.Chronicle` package on NuGet at retrieval), distributed as the `cratis/chronicle` Docker image. JVM client `io.cratis:chronicle` 2.10.0 (latest release on Maven Central at retrieval) | [nuget.org listing for `Cratis.Chronicle`](https://www.nuget.org/packages/Cratis.Chronicle); [hub.docker.com/r/cratis/chronicle](https://hub.docker.com/r/cratis/chronicle); [Maven Central metadata for `io.cratis:chronicle`](https://repo1.maven.org/maven2/io/cratis/chronicle/maven-metadata.xml) (retrieved 2026-08-29) | - -## The comparison matrix +| --- | --- | --- | +| Axon Framework | 5.3.1; Axon Server documentation from the current installation and 2026.1 reference series where applicable | [Axon Framework 5.3.1 on Maven Central](https://central.sonatype.com/artifact/org.axonframework/axon-messaging/5.3.1), [Axon 5.3 reference](https://docs.axoniq.io/axon-framework-reference/5.3/) | +| KurrentDB | Server 26.0 documentation series; Java client 1.2.1 | [KurrentDB 26.0 installation documentation](https://docs.kurrent.io/server/v26.0/quick-start/installation.html), [Java client 1.2.1 on Maven Central](https://central.sonatype.com/artifact/io.kurrent/kurrentdb-client/1.2.1) | +| Cratis Chronicle | Server and .NET distribution 16.42.0; JVM client 2.10.0 | [Cratis.Chronicle 16.42.0 on NuGet](https://www.nuget.org/packages/Cratis.Chronicle/16.42.0), [JVM client 2.10.0 on Maven Central](https://central.sonatype.com/artifact/io.cratis/chronicle/2.10.0) | -| Row | Axon Framework (5.3.1) | KurrentDB (server 26.0, Java client 1.2.1) | Cratis Chronicle (17.0.0, JVM client 2.10.0) | -| --- | ---------------------- | ------------------------------------------ | -------------------------------------------- | -| License | Axon Framework is licensed under the Apache License 2.0 (repository `LICENSE.txt`). Axon Server ships as a single artifact that "will now automatically adjust" depending on the presence of a license; the AxonIQ Developer edition is documented as "entirely free to use" and "limited to a single node", with paid Professional and Enterprise editions. | Server: Kurrent License v1 (KLv1). The KurrentDB documentation states the source code is available to view and that KLv1 "is not an OSI-approved Open Source License"; enterprise features are enabled with a license key. Java client: Apache License 2.0 (repository `LICENSE`). | MIT License, for both the server and the JVM client (repository `LICENSE` files). | -| Storage model | Framework with a pluggable `EventStorageEngine`. Documented engines at 5.3: `AxonServerEventStorageEngine` (default when using Axon Server), `PostgresqlEventStorageEngine` (stores events directly in a PostgreSQL 16+ database; the default engine when running without Axon Server), `AggregateBasedJpaEventStorageEngine` (JPA-compatible databases), and an in-memory engine for testing. "The default Event Bus (and Event Store) is Axon Server." | Purpose-built, event-native database; events are stored in streams inside KurrentDB's own storage engine. | Event-sourcing database with a documented MongoDB storage backend and "an extensible model for other data stores" (repository README wording). | -| JVM programming model | Building blocks for DDD, CQRS, and event sourcing running inside your JVM application: command, event, and query handlers, event-sourced entities (declarative, `@EventSourcedEntity`, or `@EventSourced` with Spring Boot), command routing, and repositories. | Client SDK "written in Java for use with languages on the JVM", compatible with Java 8 and above; GA versions published to Maven Central. The Java client is one of the official gRPC client SDKs listed in the server documentation. Application-layer patterns such as aggregates and CQRS are built in your own code on top of the client. | One artifact usable from both Kotlin and Java: events are data classes or records with `@EventType`, read models are classes with `@ReadModel`, and reducers, reactors, projections, and constraints follow the same annotation pattern. Artifacts on the classpath are discovered and registered with the kernel on connect. Kotlin gets suspending calls; Java gets blocking bridges for the same surface. | -| Spring Boot integration | Official Spring Boot starter `org.axonframework.extensions.spring:axon-spring-boot-starter`. Auto-configuration detects and registers message handlers (`@CommandHandler`, `@EventHandler`, `@QueryHandler`) and `@EventSourced` entities, configures the buses and event processors, and ties Axon's lifecycle to the Spring context. | No entry compiled for this row; per the caveats, absence means only that it was not found in the sources cited for this page. | Official Spring Boot starter `io.cratis:chronicle-spring-boot-starter`. The starter brings the client, discovers and registers artifacts in the application's packages before the first request is served, activates artifacts through the Spring container, and gives every request an identity, a causation trail, and a unit of work, with documented multi-tenant routing from a header, a subdomain, or a claim. | -| Subscriptions / event processing | Event processors in two forms: subscribing (invoked by the publishing mechanism's thread, or fed by an Axon Server persistent stream) and streaming (pull events using tracking tokens). The default processor is the `PooledStreamingEventProcessor`, with segmented parallel processing and replay support via reset tokens. | Catch-up subscriptions (client keeps position) and persistent subscriptions (server keeps position, competing-consumers pattern, at-least-once delivery across consumer groups), served over gRPC to the official clients. | Reactors (react to events as they occur), Reducers (transform events into typed read models), and Observers (low-level event subscriptions with guaranteed delivery), as documented in the server repository README; the JVM client declares reactors and reducers with `@Reactor` and `@Reducer` annotations. | -| Projections / read models | Read models are maintained by event handling components assigned to event processors; streaming processors support replays (reset tokens with `@ResetHandler` hooks) to rebuild them. | Server-side projections subsystem: built-in (system) projections and user-defined JavaScript projections; projections require the event body to be JSON. The docs note many read-model problems are better served by a separate read model populated by a catch-up subscription. | Declarative projections declared from the JVM client with `IProjectionFor` or `@FromEvent` on the read model, producing typed read models retrievable by key through the client. | -| Hosting model | The framework runs inside your JVM application. Axon Server is a separate server process: a single artifact installable by download, Docker, Docker Compose, Kubernetes, or Linux packages, whose available features depend on the presence of a license; the free Developer edition is limited to a single node. Running without Axon Server against PostgreSQL is documented at 5.3. | Separate database server process: single node or a highly-available cluster (three nodes for cluster deployment); installable from Linux package repositories, on Windows via Chocolatey, via Docker images, or on Kubernetes via the Operator; some features require a license key. | Separate server (Chronicle Kernel) run via the `cratis/chronicle` Docker image, exposing gRPC, REST API, and the Web Workbench management dashboard on a single port; the `latest-development` image bundles MongoDB for local development. | +## Core comparison -### Row sources +| Question | Axon Framework 5.3.1 | KurrentDB 26.0 with Java client 1.2.1 | Cratis Chronicle 16.42.0 with JVM client 2.10.0 | +| --- | --- | --- | --- | +| What is the product boundary? | A JVM application framework covering commands, events, queries, event-sourced entities, repositories, buses, and event processors. Event storage is pluggable. | A separate event-native database server. The Java client provides access from JVM applications without prescribing their application architecture. | A separate event-sourcing server and processing runtime. The JVM client declares event types, read models, projections, reducers, reactors, and constraints. | +| Where are events stored? | Axon Server is the default event store. Axon 5.3 also documents a PostgreSQL 16+ storage engine, a JPA-compatible aggregate storage engine, and an in-memory testing engine. | In streams managed by KurrentDB's storage engine. | Through Chronicle's documented server storage providers. The same server is used by the .NET, TypeScript, JVM, and Elixir clients. | +| What is the JVM programming model? | Annotated or declarative command, event, and query handlers; event-sourced entities; repositories; command, event, and query buses; and configurable event processors. | An official Java gRPC client for reading, appending, and subscribing to events. DDD, CQRS, aggregate, and read-model patterns are implemented by the application or other libraries. | Kotlin data classes or Java records annotated as events, annotated read models, and declarative or imperative processing artifacts discovered and registered with the server. Kotlin uses suspending APIs; Java uses blocking bridges. | +| What does Spring Boot integration provide? | The official starter detects handlers and event-sourced entities, configures command, event, and query buses, sets up event processors, and wires repositories and infrastructure. Auto-configured components can be replaced. | No Spring application framework is supplied by the server or Java client sources used for this page. This says nothing about community integration or ordinary Spring configuration around the client. | The official starter brings in the JVM client, discovers and registers application artifacts, activates them through the Spring container, and documents request identity, causation, units of work, and tenant routing. | +| How are events processed? | Subscribing and streaming processors invoke event handlers. Pooled streaming is the documented default; processor configuration covers segmentation, parallel processing, tracking, and replay. | Catch-up subscriptions keep position in the client. Persistent subscriptions keep position on the server and support consumer groups, acknowledgements, retries, parked events, and replay. KurrentDB documents at-least-once delivery and no ordering guarantee for persistent subscriptions. | Reactors handle event-driven application work, Reducers derive typed read models, and Observers provide low-level subscriptions. The JVM client declares Reactors and Reducers with annotations. | +| How are read models produced? | Event-handling components assigned to event processors update application-owned read models; streaming processors support replay through reset tokens and reset handlers. | Built-in and user-defined JavaScript projections can emit or link events. KurrentDB also documents catch-up subscriptions as the better fit for many application read models. | Reducers and declarative projections produce typed read models retrievable through the JVM client. | +| How can events reach other systems? | Axon documents event distribution within and across bounded contexts through Axon Server contexts or a separate message broker, with explicit context mapping recommended. | Server-side Connectors filter or transform events and send them to external sinks; clients can also consume subscriptions directly. | The server exposes gRPC and REST APIs; Reactors and JVM webhook definers provide application-defined paths for event-driven work outside the process. | +| What runs in production? | Axon Framework runs inside the JVM application. Axon Server, when selected, runs separately; PostgreSQL or JPA storage can be selected instead. Available Axon Server capabilities depend on the chosen edition and license. | A separate KurrentDB server, as a single node or documented cluster topology, plus the Java client in the application. Some features require a license key. | The Chronicle Kernel runs as a separate Docker-hosted server; the JVM client and optional Spring Boot starter run in the application. Workbench is bundled with the server. | +| What is the license boundary? | Axon Framework is Apache License 2.0. Axon Server has free and paid editions with different capabilities. | Kurrent License v1 for the server; KurrentDB states that it is not an OSI-approved open-source license. The Java client is Apache License 2.0. | MIT License for Chronicle and the JVM client. Other Cratis products retain their own license and release boundaries. | -All retrieved 2026-08-29: +## Where each option fits -- **Axon Framework / Axon Server** — framework identity and positioning: [github.com/AxonIQ/AxonFramework `README.md`](https://github.com/AxonIQ/AxonFramework/blob/master/README.md); license: [github.com/AxonIQ/AxonFramework `LICENSE.txt`](https://github.com/AxonIQ/AxonFramework/blob/master/LICENSE.txt) (Apache-2.0); event store, storage engines, default event bus/store, multi-context: [docs.axoniq.io/axon-framework-reference/5.3/events/infrastructure/](https://docs.axoniq.io/axon-framework-reference/5.3/events/infrastructure/); event processors, subscribing/streaming, replay: [docs.axoniq.io/axon-framework-reference/5.2/events/event-processors/](https://docs.axoniq.io/axon-framework-reference/5.2/events/event-processors/) and [docs.axoniq.io/axon-framework-reference/5.3/events/event-processors/subscribing/](https://docs.axoniq.io/axon-framework-reference/5.3/events/event-processors/subscribing/); event-sourced entities: [docs.axoniq.io/axon-framework-reference/5.0/commands/entities/event-sourced-entity/](https://docs.axoniq.io/axon-framework-reference/5.0/commands/entities/event-sourced-entity/); Spring Boot starter and component detection: [docs.axoniq.io/axon-framework-reference/5.3/spring-boot-integration/](https://docs.axoniq.io/axon-framework-reference/5.3/spring-boot-integration/) and [docs.axoniq.io/axon-framework-reference/5.3/configuration/spring/](https://docs.axoniq.io/axon-framework-reference/5.3/configuration/spring/); Axon Server editions, single artifact, license behavior, install channels: [docs.axoniq.io/axon-server-installation/](https://docs.axoniq.io/axon-server-installation/), [docs.axoniq.io/axon-server-installation/developer/](https://docs.axoniq.io/axon-server-installation/developer/), and [docs.axoniq.io/axon-server-reference/v2026.1/axon-server/installation/local-installation/](https://docs.axoniq.io/axon-server-reference/v2026.1/axon-server/installation/local-installation/); framework version: [Maven Central metadata for `org.axonframework:axon-messaging`](https://repo1.maven.org/maven2/org/axonframework/axon-messaging/maven-metadata.xml) (5.3.1). -- **KurrentDB** — server license, official client list including Java, protocols: [docs.kurrent.io/server/v26.0/quick-start/](https://docs.kurrent.io/server/v26.0/quick-start/) (Introduction); hosting, packages, Docker, Kubernetes Operator, license keys, 26.0.3: [docs.kurrent.io/server/v26.0/quick-start/installation.html](https://docs.kurrent.io/server/v26.0/quick-start/installation.html); projections: [docs.kurrent.io/server/v26.0/features/projections/](https://docs.kurrent.io/server/v26.0/features/projections/); persistent subscriptions: [docs.kurrent.io/server/v26.0/features/persistent-subscriptions.html](https://docs.kurrent.io/server/v26.0/features/persistent-subscriptions.html); Java client identity, Java 8+, Maven Central, server compatibility: [github.com/kurrent-io/KurrentDB-Client-Java `README.md`](https://github.com/kurrent-io/KurrentDB-Client-Java/blob/trunk/README.md); Java client license: [github.com/kurrent-io/KurrentDB-Client-Java `LICENSE`](https://github.com/kurrent-io/KurrentDB-Client-Java/blob/trunk/LICENSE) (Apache-2.0); client version: [Maven Central metadata for `io.kurrent:kurrentdb-client`](https://repo1.maven.org/maven2/io/kurrent/kurrentdb-client/maven-metadata.xml) (1.2.1). -- **Cratis Chronicle** — server identity, MongoDB backend, reactors/reducers/projections/observers, Docker hosting, Workbench: [github.com/Cratis/Chronicle `README.md`](https://github.com/Cratis/Chronicle/blob/main/README.md); server license: [github.com/Cratis/Chronicle `LICENSE`](https://github.com/Cratis/Chronicle/blob/main/LICENSE) (MIT); JVM client identity, annotations, discovery, coroutines and Java bridges, Spring Boot starter, testing module, license: [github.com/Cratis/Chronicle.Kotlin `README.md`](https://github.com/Cratis/Chronicle.Kotlin/blob/main/README.md) and [`LICENSE`](https://github.com/Cratis/Chronicle.Kotlin/blob/main/LICENSE) (MIT); versions: [nuget.org](https://www.nuget.org/packages/Cratis.Chronicle) (`Cratis.Chronicle` 17.0.0), [Maven Central metadata for `io.cratis:chronicle`](https://repo1.maven.org/maven2/io/cratis/chronicle/maven-metadata.xml) (2.10.0), [hub.docker.com/r/cratis/chronicle](https://hub.docker.com/r/cratis/chronicle). +These are not quality rankings. They identify the architectural choice each product makes most explicit. -## Ecosystem and supporting products +### Axon Framework and Axon Server -An event store rarely ships alone. Each of the compared tools names its own supporting products; the same method applies here — every cell restates the named vendor's own public listing or documentation, with retrieval dates, and implies nothing about quality, integration depth, or superiority. +Examine Axon closely when you want a JVM application framework to define command, event, and query handling; event-sourced entities; repositories; buses; and processing as one model. Its Spring Boot integration and storage-engine choices are central parts of that experience. Axon Server adds event storage and message routing, while the documented PostgreSQL and JPA paths allow different infrastructure choices. -| Row | Axon Framework (5.3.1) | KurrentDB (server 26.0, Java client 1.2.1) | Cratis Chronicle (17.0.0, JVM client 2.10.0) | -| --- | ---------------------- | ------------------------------------------ | -------------------------------------------- | -| Wider product family | The framework README names Axon Server ("a distributed command bus, event bus, query bus, and an efficient event store implementation for scalable event sourcing") and states the Axon Framework organization "has several extensions". The Axon Server documentation names the Axoniq Platform: connecting Axon Server to it "can unlock additional functionality" and "is all free up to 10 connected applications at a time". | Official gRPC client SDKs listed for Python, Node.js (JavaScript/TypeScript), Java, .NET, Go, and Rust; community clients listed for Ruby, Elixir, and PHP; the documented server feature set includes projections, persistent subscriptions, and a Connectors subsystem (next row). | Part of the Cratis ecosystem: [Arc](/arc/) (an opinionated CQRS application framework for ASP.NET Core with commands, queries, validation, authorization, and TypeScript proxy generation), [Components](/components/) (a React component library aligned with Arc application patterns), the [Cratis CLI](/cli/) (terminal workflows for inspecting and diagnosing Chronicle), and the Web Workbench management dashboard exposed by the server. Released clients for .NET, TypeScript, JVM, and Elixir; AI agents connect through the [Chronicle MCP server](/ai/). | -| Pushing events to other systems | Event handling components run by event processors react to events in the application; the framework documentation describes Axon Server's Multi-Context solution for distributing events between bounded contexts. | Server-side Connectors subsystem, documented as pre-installed and enabled by default: each connector runs a catch-up subscription that can filter or transform events and push them to an external system via a sink. | The server exposes gRPC and REST APIs (see the Hosting model row); Reactors provide documented event-driven processing, and the JVM client documents webhook definers that push events "out to something beyond your process". | -| AI assistance | The framework README references "Ask Axon Guru", described as "an Axon-focused AI to answer your questions". | No entry compiled for this row; per the caveats, absence means only that it was not found in the sources cited for this page. | Cratis documents free AI skills, rules, and diagnostics for AI-assisted development on the [AI page](/ai/); the JVM client README describes the ecosystem as "AI-friendly by design". Current availability and distribution status are stated on the AI page. | +### KurrentDB -### Ecosystem row sources +Examine KurrentDB closely when you want the event store to be dedicated infrastructure, need a JVM client alongside clients for other languages, or want server-managed persistent subscriptions and connectors while keeping the JVM application architecture in your own code. -All retrieved 2026-08-29: +### Cratis Chronicle -- **Axon** — Axon Server description, extensions, Ask Axon Guru: [github.com/AxonIQ/AxonFramework `README.md`](https://github.com/AxonIQ/AxonFramework/blob/master/README.md); Axoniq Platform wording: [docs.axoniq.io/axon-server-installation/developer/](https://docs.axoniq.io/axon-server-installation/developer/); Multi-Context: [docs.axoniq.io/axon-framework-reference/5.3/events/infrastructure/](https://docs.axoniq.io/axon-framework-reference/5.3/events/infrastructure/). -- **KurrentDB** — client SDK list: [docs.kurrent.io/server/v26.0/quick-start/](https://docs.kurrent.io/server/v26.0/quick-start/); Connectors overview (pre-installed, enabled by default, catch-up subscription, filter/transform, sinks): [docs.kurrent.io/server/v26.0/features/connectors/](https://docs.kurrent.io/server/v26.0/features/connectors/). -- **Cratis Chronicle** — Arc: [cratis.io/arc/](https://cratis.io/arc/); Components: [cratis.io/components/](https://cratis.io/components/); CLI: [cratis.io/cli/](https://cratis.io/cli/); Workbench: [github.com/Cratis/Chronicle `README.md`](https://github.com/Cratis/Chronicle/blob/main/README.md); webhook definers, ecosystem listing, AI wording: [github.com/Cratis/Chronicle.Kotlin `README.md`](https://github.com/Cratis/Chronicle.Kotlin/blob/main/README.md); AI skills, rules, and diagnostics: [cratis.io/ai/](https://cratis.io/ai/). +Examine Chronicle closely when you want event storage and event processing behind a separate runtime while declaring typed JVM artifacts through Kotlin, Java, or Spring Boot. Chronicle's broader Cratis application ecosystem is currently centered on .NET and React; JVM teams should evaluate the Chronicle JVM client and Spring Boot starter on their own documented behavior rather than assuming parity with that .NET application path. -## Caveats and limitations +## Questions to answer before choosing -- **This matrix compares documentation, not behavior.** Every cell restates what the named tool's own public documentation or registry listing says at the named version and retrieval date. It does not test, measure, or rank anything, and absence of a capability from a cell means only that it was not found in the cited source — not that the tool lacks it. -- **A framework and a database answer different questions.** Axon Framework is a framework with pluggable storage; KurrentDB and Chronicle are databases with clients. The rows state what each tool's documentation says about its own shape; they do not rank the shapes. -- **Client existence is not client parity.** A listed client package says nothing about feature coverage relative to the primary client — for any tool in this table, including Chronicle's JVM client relative to its .NET SDK. -- **An ecosystem listing is not an integration or quality claim.** The ecosystem rows restate each vendor's own product-family listing at the retrieval date. They say nothing about how well the pieces work together, how complete any supporting product is, or how the families compare — and an empty or missing entry means only that nothing was found in the cited sources. -- **Chronicle's storage-provider breadth beyond the documented MongoDB backend is not stated as a row fact.** Public Chronicle documentation at the compared version documents a MongoDB backend with an extensible storage model; the row sticks to that cited wording. -- **Licensing nuance, for two of the three.** The license rows quote each vendor's own documentation; read KLv1 and the Axon Server edition terms yourself. Axon Framework itself is Apache-2.0; Axon Server's features depend on edition and license. This page draws no conclusion about fitness of any license for any use. -- **Documentation series differ from patch versions.** Axon Framework facts are cited from the 5.3 reference series (with two rows citing 5.2 and 5.0 pages where the 5.3 page splits content); KurrentDB facts from the server v26.0 series. A patch release inside a series may change details without changing the cited page. -- **Versions move.** Each compared tool releases on its own cadence; every cell is pinned to the versions and retrieval dates above and may be stale the day after retrieval. +1. **Framework boundary:** Do you want a JVM framework to own commands, queries, entities, repositories, and event processing, or do you want an event server behind an application model you choose separately? +2. **Storage boundary:** Should events live in Axon Server, PostgreSQL or JPA through Axon, KurrentDB's own engine, or one of Chronicle's documented providers? +3. **Spring boundary:** Do you need a complete CQRS application framework integrated with Spring, a Spring-configured database client, or Chronicle artifact registration and request integration? +4. **Processing model:** Which handlers must share a transaction, which processors must be replayable, and where should checkpoints, retries, and failed work be owned? +5. **Language boundary:** Is the JVM the complete system boundary, or must several language clients use the same event server? +6. **Operations:** How will your team inspect processor or subscription progress, failed processing, projections, replay, and recovery for the exact topology you deploy? +7. **Commercial and license boundary:** Which server edition, support terms, and licenses apply to the exact components you intend to run? -## How to choose +## Limitations -Rather than a winner, use fit questions: +- This is a documentation comparison, not a benchmark or production evaluation. +- Axon Framework is broader than a database client. The table compares overlapping concerns without treating the difference as an advantage or deficiency by itself. +- Client availability does not establish client parity. +- Storage-engine or provider availability does not establish parity between implementations. +- Product-family membership does not establish integration depth, common maturity, compatibility, support, or one commercial boundary. +- Versions and documentation change independently; verify the cited sources against the release you plan to adopt. -- **Do you want a framework that structures your whole application, or a database behind code you structure yourself?** A DDD/CQRS framework gives you aggregates, buses, and processors as first-class citizens — and its conventions. A database with a client leaves the application architecture entirely to you. -- **Where should events live?** One candidate defaults to its own server but documents PostgreSQL and JPA storage engines; one is itself the storage engine; one is a database with a documented MongoDB backend. Which operational surface does your team already run? -- **How much of the read side do you want designed for you?** Compare writing event handling components and processors yourself against declaring reducers and projections that the server executes. -- **Is Spring Boot your baseline?** Two of the three document an official Spring Boot starter; compare what each starter actually auto-configures — handlers and buses, or discovery, tenancy, and per-request units of work. -- **Is your organization polyglot?** Check which client languages are first-party and what each client actually supports — client existence is not client parity, for any tool including ours. -- **Who explains the system at 3 a.m.?** Compare the operational surfaces: what does each tool show you about processor or observer progress, failed projections, and replay? +## Sources -## What we deliberately did not claim +Sources checked 2026-08-30: -This comparison states released, verifiable facts. It does not claim any tool is faster, more scalable, more reliable, or more production-proven than another — those claims require benchmarks and evidence this page does not carry. Where a capability is listed for Chronicle, it comes from the named released version; the same courtesy is extended to every tool compared, from that tool's own documentation. +- **Axon:** [Axon Framework repository](https://github.com/AxonIQ/AxonFramework), [event infrastructure and storage engines](https://docs.axoniq.io/axon-framework-reference/5.3/events/infrastructure/), [Spring Boot integration](https://docs.axoniq.io/axon-framework-reference/5.3/spring-boot-integration/), [event processors](https://docs.axoniq.io/axon-framework-reference/5.3/events/event-processors/), [Axon Server installation](https://docs.axoniq.io/axon-server-installation/), and [Apache-2.0 license](https://github.com/AxonIQ/AxonFramework/blob/master/LICENSE.txt). +- **KurrentDB:** [introduction and clients](https://docs.kurrent.io/server/v26.0/quick-start/), [installation](https://docs.kurrent.io/server/v26.0/quick-start/installation.html), [persistent subscriptions](https://docs.kurrent.io/server/v26.0/features/persistent-subscriptions.html), [projections](https://docs.kurrent.io/server/v26.0/features/projections/), [Connectors](https://docs.kurrent.io/server/v26.0/features/connectors/), [Java client](https://github.com/kurrent-io/KurrentDB-Client-Java), and [Java-client license](https://github.com/kurrent-io/KurrentDB-Client-Java/blob/trunk/LICENSE). +- **Cratis Chronicle:** [Chronicle repository](https://github.com/Cratis/Chronicle), [JVM client repository](https://github.com/Cratis/Chronicle.Kotlin), [Spring Boot guide](https://github.com/Cratis/Chronicle.Kotlin/blob/main/Documentation/guides/spring-boot.md), [Chronicle license](https://github.com/Cratis/Chronicle/blob/main/LICENSE), [JVM-client license](https://github.com/Cratis/Chronicle.Kotlin/blob/main/LICENSE), [NuGet](https://www.nuget.org/packages/Cratis.Chronicle/16.42.0), [Maven Central](https://central.sonatype.com/artifact/io.cratis/chronicle/2.10.0), and [Docker Hub](https://hub.docker.com/r/cratis/chronicle/tags). -## How this page stays current +## Corrections and refresh -This matrix is re-verified — every cell checked against the then-current released versions with new retrieval dates — whenever a compared tool ships a new major or minor server/package release, a compared tool changes its license or client list, or 90 days elapse since the last recorded retrieval date. If a compared tool disputes a row and it cannot be re-verified, the row is corrected or removed. +We recheck this page when a compared product changes a relevant major or minor release, license, client list, or documented capability, and at least every 90 days. If a statement cannot be confirmed from the named product's own current public sources, we correct or remove it. -If you spot a cell that no longer matches its source, [tell us](/feedback/) — we will re-verify and fix it. +If you find a factual error or a better first-party source, [send the correction](/feedback/).