ExESDB is a reincarnation of rabbitmq/khepri, specialized to use khepri as a BEAM-native Event Store
Elixir
66
171 commits
updated Sep 2, 2026
ExESDB is a BEAM-native Event Store, built on top of the khepri and ra subsystems.
One of the arguments for BEAM development is that it comes "batteries included". Be it caching, storage, pub/sub, observability etc... the Erlang ecosystem always has the option to avoid external dependencies.
For Event Sourcing use cases however, the Event Store is often a separate service.
This project is an attempt at addressing this point, by building further upon the work of the rabbitmq/khepri and rabbitmq/ra subsystems.
ExESDB is a distributed, BEAM-native Event Store that provides high-availability event sourcing capabilities with automatic cluster formation and coordination. Built on top of Khepri and Ra (Raft consensus), it offers enterprise-grade reliability and performance.
:by_stream - Subscribe to specific event streams:by_event_type - Subscribe to events by type classification:by_event_pattern - Pattern-based event matching:by_event_payload - Content-based subscription filteringExESDB uses LibCluster for automatic cluster discovery and formation:
EX_ESDB_STORE_ID: Unique identifier for the store instanceEX_ESDB_DB_TYPE: Deployment type (:single or :cluster)EX_ESDB_DATA_DIR: Data directory for persistent storageEX_ESDB_TIMEOUT: Operation timeout configurationEX_ESDB_CLUSTER_SECRET: Shared secret for cluster authenticationEX_ESDB_COOKIE: Erlang distribution cookieEX_ESDB_PUB_SUB: PubSub configuration for event broadcastingconfig :libcluster,
topologies: [
ex_esdb_cluster: [
strategy: Cluster.Strategy.Gossip,
config: [
port: 45_892,
if_addr: "0.0.0.0",
multicast_addr: "255.255.255.255",
broadcast_only: true,
secret: System.get_env("EX_ESDB_CLUSTER_SECRET")
]
]
]
┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐
│ ExESDB Node │ │ ExESDB Node │ │ ExESDB Node │
│ (Leader) │◄──►│ (Follower) │◄──►│ (Follower) │
│ Khepri + Ra │ │ Khepri + Ra │ │ Khepri + Ra │
└─────────────────┘ └─────────────────┘ └─────────────────┘
▲ ▲ ▲
│ │ │
│ Gossip Multicast Network (UDP:45892) │
│ │ │
▼ ▼ ▼
Raft Consensus Event Storage Subscription
& Replication & Retrieval Management
ExESDB is available as a Docker image on Docker Hub with automatic versioning based on the mix.exs version.
beamcampus/ex_esdb:latest - Latest build from master branchbeamcampus/ex_esdb:0.0.18 - Specific version (current version)beamcampus/ex_esdb:0.0.x - Any specific version tagSingle Node:
docker run -d \
--name ex-esdb \
-p 4369:4369 \
-p 9000-9100:9000-9100 \
-p 45892:45892/udp \
-e EX_ESDB_STORE_ID="my-store" \
-e EX_ESDB_DB_TYPE="single" \
-e EX_ESDB_DATA_DIR="/data" \
-v ex-esdb-data:/data \
beamcampus/ex_esdb:latest
Multi-Node Cluster:
# Node 1 (seed node)
docker run -d \
--name ex-esdb-node1 \
--network ex-esdb-net \
-p 4369:4369 \
-p 9001:9000 \
-p 45892:45892/udp \
-e EX_ESDB_STORE_ID="cluster-store" \
-e EX_ESDB_DB_TYPE="cluster" \
-e EX_ESDB_DATA_DIR="/data" \
-e EX_ESDB_CLUSTER_SECRET="your-secret-key" \
-e EX_ESDB_COOKIE="your-erlang-cookie" \
-v ex-esdb-node1-data:/data \
beamcampus/ex_esdb:latest
# Node 2
docker run -d \
--name ex-esdb-node2 \
--network ex-esdb-net \
-p 9002:9000 \
-e EX_ESDB_STORE_ID="cluster-store" \
-e EX_ESDB_DB_TYPE="cluster" \
-e EX_ESDB_DATA_DIR="/data" \
-e EX_ESDB_CLUSTER_SECRET="your-secret-key" \
-e EX_ESDB_COOKIE="your-erlang-cookie" \
-v ex-esdb-node2-data:/data \
beamcampus/ex_esdb:latest
# Node 3
docker run -d \
--name ex-esdb-node3 \
--network ex-esdb-net \
-p 9003:9000 \
-e EX_ESDB_STORE_ID="cluster-store" \
-e EX_ESDB_DB_TYPE="cluster" \
-e EX_ESDB_DATA_DIR="/data" \
-e EX_ESDB_CLUSTER_SECRET="your-secret-key" \
-e EX_ESDB_COOKIE="your-erlang-cookie" \
-v ex-esdb-node3-data:/data \
beamcampus/ex_esdb:latest
For development and testing, use the provided Docker Compose setup:
# Clone the repository
git clone https://github.com/beam-campus/ex-esdb.git
cd ex-esdb/dev-env
# Start a 3-node cluster
./start-core-only.sh
# Or use the interactive cluster manager
./ez-cluster.sh
The Docker Compose setup includes:
📌 Important: When using the dev-env Docker Compose configurations, you must export the
EX_ESDB_COOKIEenvironment variable on your host machine. This single environment variable is used for all cluster authentication purposes (cookies, secrets, etc.).export EX_ESDB_COOKIE="your-secure-cookie-value"
| Variable | Description | Default | Required |
|---|---|---|---|
EX_ESDB_STORE_ID | Unique store identifier | - | Yes |
EX_ESDB_DB_TYPE | Deployment type (single or cluster) | single | No |
EX_ESDB_DATA_DIR | Data directory path | /data | No |
EX_ESDB_TIMEOUT | Operation timeout (ms) | 5000 | No |
EX_ESDB_CLUSTER_SECRET | Cluster authentication secret | - | Yes (cluster) |
EX_ESDB_COOKIE | Erlang distribution cookie | - | Yes (cluster) |
EX_ESDB_PUB_SUB | PubSub process name | :ex_esdb_pubsub | No |
| Port | Protocol | Description |
|---|---|---|
4369 | TCP | EPMD (Erlang Port Mapper Daemon) |
9000-9100 | TCP | Erlang distribution ports |
45892 | UDP | LibCluster gossip multicast |
The Docker image includes a built-in health check script:
# Check container health
docker exec ex-esdb ./check-ex-esdb.sh
# View health status
docker inspect --format='{{.State.Health.Status}}' ex-esdb
EX_ESDB_CLUSTER_SECRET and EX_ESDB_COOKIEExESDB is also available as a Hex package for direct integration:
def deps do
[
{:ex_esdb, "~> 0.0.18"}
]
end
Elixir
91.3%
Shell
5.8%
Erlang
2.1%
ExESDB is a reincarnation of rabbitmq/khepri, specialized to use khepri as a BEAM-native Event Store
Elixir
66
171 commits
updated Sep 2, 2026
ExESDB is a BEAM-native Event Store, built on top of the khepri and ra subsystems.
One of the arguments for BEAM development is that it comes "batteries included". Be it caching, storage, pub/sub, observability etc... the Erlang ecosystem always has the option to avoid external dependencies.
For Event Sourcing use cases however, the Event Store is often a separate service.
This project is an attempt at addressing this point, by building further upon the work of the rabbitmq/khepri and rabbitmq/ra subsystems.
ExESDB is a distributed, BEAM-native Event Store that provides high-availability event sourcing capabilities with automatic cluster formation and coordination. Built on top of Khepri and Ra (Raft consensus), it offers enterprise-grade reliability and performance.
:by_stream - Subscribe to specific event streams:by_event_type - Subscribe to events by type classification:by_event_pattern - Pattern-based event matching:by_event_payload - Content-based subscription filteringExESDB uses LibCluster for automatic cluster discovery and formation:
EX_ESDB_STORE_ID: Unique identifier for the store instanceEX_ESDB_DB_TYPE: Deployment type (:single or :cluster)EX_ESDB_DATA_DIR: Data directory for persistent storageEX_ESDB_TIMEOUT: Operation timeout configurationEX_ESDB_CLUSTER_SECRET: Shared secret for cluster authenticationEX_ESDB_COOKIE: Erlang distribution cookieEX_ESDB_PUB_SUB: PubSub configuration for event broadcastingconfig :libcluster,
topologies: [
ex_esdb_cluster: [
strategy: Cluster.Strategy.Gossip,
config: [
port: 45_892,
if_addr: "0.0.0.0",
multicast_addr: "255.255.255.255",
broadcast_only: true,
secret: System.get_env("EX_ESDB_CLUSTER_SECRET")
]
]
]
┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐
│ ExESDB Node │ │ ExESDB Node │ │ ExESDB Node │
│ (Leader) │◄──►│ (Follower) │◄──►│ (Follower) │
│ Khepri + Ra │ │ Khepri + Ra │ │ Khepri + Ra │
└─────────────────┘ └─────────────────┘ └─────────────────┘
▲ ▲ ▲
│ │ │
│ Gossip Multicast Network (UDP:45892) │
│ │ │
▼ ▼ ▼
Raft Consensus Event Storage Subscription
& Replication & Retrieval Management
ExESDB is available as a Docker image on Docker Hub with automatic versioning based on the mix.exs version.
beamcampus/ex_esdb:latest - Latest build from master branchbeamcampus/ex_esdb:0.0.18 - Specific version (current version)beamcampus/ex_esdb:0.0.x - Any specific version tagSingle Node:
docker run -d \
--name ex-esdb \
-p 4369:4369 \
-p 9000-9100:9000-9100 \
-p 45892:45892/udp \
-e EX_ESDB_STORE_ID="my-store" \
-e EX_ESDB_DB_TYPE="single" \
-e EX_ESDB_DATA_DIR="/data" \
-v ex-esdb-data:/data \
beamcampus/ex_esdb:latest
Multi-Node Cluster:
# Node 1 (seed node)
docker run -d \
--name ex-esdb-node1 \
--network ex-esdb-net \
-p 4369:4369 \
-p 9001:9000 \
-p 45892:45892/udp \
-e EX_ESDB_STORE_ID="cluster-store" \
-e EX_ESDB_DB_TYPE="cluster" \
-e EX_ESDB_DATA_DIR="/data" \
-e EX_ESDB_CLUSTER_SECRET="your-secret-key" \
-e EX_ESDB_COOKIE="your-erlang-cookie" \
-v ex-esdb-node1-data:/data \
beamcampus/ex_esdb:latest
# Node 2
docker run -d \
--name ex-esdb-node2 \
--network ex-esdb-net \
-p 9002:9000 \
-e EX_ESDB_STORE_ID="cluster-store" \
-e EX_ESDB_DB_TYPE="cluster" \
-e EX_ESDB_DATA_DIR="/data" \
-e EX_ESDB_CLUSTER_SECRET="your-secret-key" \
-e EX_ESDB_COOKIE="your-erlang-cookie" \
-v ex-esdb-node2-data:/data \
beamcampus/ex_esdb:latest
# Node 3
docker run -d \
--name ex-esdb-node3 \
--network ex-esdb-net \
-p 9003:9000 \
-e EX_ESDB_STORE_ID="cluster-store" \
-e EX_ESDB_DB_TYPE="cluster" \
-e EX_ESDB_DATA_DIR="/data" \
-e EX_ESDB_CLUSTER_SECRET="your-secret-key" \
-e EX_ESDB_COOKIE="your-erlang-cookie" \
-v ex-esdb-node3-data:/data \
beamcampus/ex_esdb:latest
For development and testing, use the provided Docker Compose setup:
# Clone the repository
git clone https://github.com/beam-campus/ex-esdb.git
cd ex-esdb/dev-env
# Start a 3-node cluster
./start-core-only.sh
# Or use the interactive cluster manager
./ez-cluster.sh
The Docker Compose setup includes:
📌 Important: When using the dev-env Docker Compose configurations, you must export the
EX_ESDB_COOKIEenvironment variable on your host machine. This single environment variable is used for all cluster authentication purposes (cookies, secrets, etc.).export EX_ESDB_COOKIE="your-secure-cookie-value"
| Variable | Description | Default | Required |
|---|---|---|---|
EX_ESDB_STORE_ID | Unique store identifier | - | Yes |
EX_ESDB_DB_TYPE | Deployment type (single or cluster) | single | No |
EX_ESDB_DATA_DIR | Data directory path | /data | No |
EX_ESDB_TIMEOUT | Operation timeout (ms) | 5000 | No |
EX_ESDB_CLUSTER_SECRET | Cluster authentication secret | - | Yes (cluster) |
EX_ESDB_COOKIE | Erlang distribution cookie | - | Yes (cluster) |
EX_ESDB_PUB_SUB | PubSub process name | :ex_esdb_pubsub | No |
| Port | Protocol | Description |
|---|---|---|
4369 | TCP | EPMD (Erlang Port Mapper Daemon) |
9000-9100 | TCP | Erlang distribution ports |
45892 | UDP | LibCluster gossip multicast |
The Docker image includes a built-in health check script:
# Check container health
docker exec ex-esdb ./check-ex-esdb.sh
# View health status
docker inspect --format='{{.State.Health.Status}}' ex-esdb
EX_ESDB_CLUSTER_SECRET and EX_ESDB_COOKIEExESDB is also available as a Hex package for direct integration:
def deps do
[
{:ex_esdb, "~> 0.0.18"}
]
end
Elixir
91.3%
Shell
5.8%
Erlang
2.1%