ReckonDB vs KurrentDB (EventStoreDB)

KurrentDB, formerly EventStoreDB, is the oldest dedicated event store and the most widely deployed. If you’ve been around event sourcing for a while, you’ve used it or evaluated it. This page is an honest comparison.


The Short Version

ReckonDB KurrentDB
Primary store Khepri/Ra (BEAM Raft) Proprietary leader election
License Apache-2.0 BSL (commercial beyond limits)
gRPC API
HTTP/JSON API ❌ (planned)
Secondary indexes ✅ tags, event type, metadata ✅ category, event type (25.1+)
Filter-based DCB
Multi-stream append (enumerate) ✅ (25.1+)
Competing consumers 🟡 (in development) ✅ persistent subscriptions
CQRS framework ✅ evoq
Managed cloud ✅ Kurrent Cloud
Erlang/Elixir native 🟡 (client library only)
Tamper resistance ✅ HMAC + hash chain

Where ReckonDB Leads

Filter-based DCB vs stream-enumeration-based multi-append

KurrentDB 25.1 added multi-stream atomic append, you can append to multiple streams in one operation with per-stream expected version checks. They market this as eliminating saga patterns for cross-aggregate consistency. It is a real improvement, and ReckonDB supports the equivalent.

But it is not the DCB pattern.

The difference is in how the consistency boundary is defined:

KurrentDB multi-stream append:

Enumerate the exact streams involved → specify expected version per stream → append atomically

You must know which streams contain the relevant events before you read. If the invariant you’re enforcing spans an open-ended set of streams (e.g., “has anyone else registered this email?”), you cannot enumerate the streams upfront without a side lookup.

ReckonDB DCB:

1. Read all events matching a tag/type filter since global position N
2. Run domain logic on those events
3. Append atomically IF nothing new matched that filter since N

The consistency boundary is a tag filter on the global log position. You don’t enumerate streams. You ask: “has any event matching {any_of, ["email:alice@acme.com"]} appeared since position 4201?” The store answers atomically inside a single Raft log entry, the read context and the conditional write are indivisible.

This distinction matters for real domains:

Use case KurrentDB multi-stream ReckonDB DCB
Unique username / email Requires naming convention to map email→stream {any_of, ["email:alice"]}, no convention needed
Seat reservation for event N Know the seat streams → works {and_,[{event_type,"seat_reserved"},{any_of,["show:42"]}]}
Credit limit across N accounts Must enumerate account streams {any_of, ["account:X","account:Y"]} with tag index
Rate limit (rolling window) Hard: window boundary is time-based, not stream-based Tag + temporal filter

Secondary indexes: custom depth

KurrentDB 25.1 added indexed reads for category and event type. These are the two most common query shapes, and KurrentDB now does them well (10× faster than system projections, 80% less storage).

ReckonDB indexes three dimensions:

Index type ReckonDB KurrentDB
Event type ✅ (25.1+)
Category / stream prefix ✅ tags ✅ (25.1+)
Arbitrary tag ✅ any value at append time
Arbitrary metadata key {meta, Key}

Custom tags and metadata indexes are what make DCB filters fast: the server-side condition check hits the index, not a full scan of the global log.

BEAM-native consensus

KurrentDB uses its own leader election algorithm (not published as a standalone specification). ReckonDB’s store is built on Ra, the Raft implementation that ships in RabbitMQ, and Khepri, used in production in RabbitMQ 4.0.

The practical difference: Ra is a scrutinised, formally-specified Raft implementation with OTP supervision trees. A failed Ra member is isolated by OTP. The BEAM actor model gives you process-level fault isolation that the JVM-based cluster coordination in KurrentDB does not have.

Tamper resistance

ReckonDB stores an HMAC + hash chain per event, verifiable at read time. KurrentDB has no equivalent. For audit log, financial records, or regulatory compliance use cases, this is a hard requirement that KurrentDB cannot satisfy without a layer above the store.

Licence

KurrentDB is under the Business Source Licence (BSL). BSL permits use below a threshold (currently production use for organisations under a certain revenue), with the restriction that it converts to Apache-2.0 after a specified period. The practical risk: if your usage exceeds the BSL threshold, you’re commercial. KurrentDB/Kurrent Cloud is the commercial offering.

ReckonDB is Apache-2.0 with no usage restrictions.


Where KurrentDB Leads

Battle-tested at scale

EventStoreDB has been in production since 2011, with documented deployments at thousands of companies. ReckonDB is young. If your requirement is “used by 10,000 teams with public post-mortems,” KurrentDB wins.

Client ecosystem

KurrentDB has official, maintained SDKs for .NET, Java, Go, Python, Node.js, and Rust. ReckonDB has Go (reckon-go) and Erlang/Elixir (evoq + reckon-evoq). If your team is Python, .NET, or Node.js, KurrentDB is ready today.

HTTP/JSON API

KurrentDB exposes a full HTTP/JSON API alongside gRPC. ReckonDB, through reckon-gateway, also offers both: gRPC plus an HTTP/JSON REST API over the core surface (and a browser admin UI). Teams that want to avoid protobuf toolchain setup can curl either store from day one.

Managed cloud

Kurrent Cloud is a fully managed KurrentDB hosting. ReckonDB requires self-hosting or your own infrastructure.

Competing consumers

KurrentDB’s persistent subscriptions with competing consumers are mature and configurable. ReckonDB’s competing consumer implementation is in development.

Web admin UI

KurrentDB ships an embedded admin UI. ReckonDB’s UI is the reckon CLI + reckon-lazy (TUI). A web UI for browsing event streams, checking stream health, and managing subscriptions does not exist yet in ReckonDB.


Who Should Choose Which

Choose ReckonDB if:

  • You need filter-based DCB, cross-aggregate consistency without enumerating streams
  • You’re building on BEAM (Erlang/Elixir) and want a native embedded store
  • You need arbitrary secondary indexes (custom tags, metadata queries)
  • Tamper resistance is a compliance requirement
  • You want Apache-2.0 with no usage restrictions
  • You’re embedding a store in a single-node mode (laptop → cluster, same API)

Choose KurrentDB if:

  • You need a .NET, Python, Java, or Node.js SDK today
  • Competing consumers (work queue delivery) are a current requirement
  • You want a managed cloud offering
  • Your organisation has used EventStoreDB for years and migration cost is high
  • You need HTTP/JSON without a protobuf toolchain

The DCB Distinction in One Paragraph

KurrentDB’s multi-stream append is stream-enumeration-based atomic write: useful, correct, a real improvement. ReckonDB’s DCB is filter-based conditional append: you give the store a tag/type filter and a position cutoff, and the store atomically checks whether any event matching that filter appeared after your cutoff position, refusing the write if one did. You never enumerate streams. The filter is evaluated inside a single Raft log entry. The two primitives solve overlapping but distinct problems; the filter-based form is strictly more expressive for open-ended consistency invariants.