Packages
ex_esdb
0.4.7
0.11.0
0.10.0
0.9.0
0.8.0
0.7.8
0.7.7
0.7.6
0.7.5
0.7.4
0.7.3
0.7.2
0.7.1
0.7.0
0.6.1
0.6.0
0.5.1
0.5.0
0.4.8
0.4.7
0.4.6
0.4.5
0.4.4
0.4.3
0.4.2
0.4.1
0.4.0
0.3.3
0.3.2
0.3.1
0.3.0
0.2.5
0.2.4
0.2.3
0.2.2
0.2.1
0.2.0
0.1.7
0.1.6
0.1.5
0.1.4
0.1.3
0.1.2
0.1.1
0.1.0
0.0.20
0.0.19
0.0.18
0.0.17
0.0.16
0.0.15
0.0.14-alpha
0.0.13-alpha
0.0.12-alpha
0.0.11-alpha
0.0.10-alpha
0.0.9-alpha
0.0.8-alpha
0.0.6-alpha
0.0.5-alpha
0.0.4-alpha
0.0.3-alpha
0.0.2-alfa
0.0.1-alfa
ExESDB is a reincarnation of rabbitmq/khepri, specialized for use as a BEAM-native event store.
Current section
Files
Jump to
Current section
Files
home/rl/work/github.com/beam-campus/ex-esdb/README.md
# ExESDB - A BEAM-native Event Store
`ExESDB` is a BEAM-native Event Store, built on top of the [khepri](https://github.com/rabbitmq/khepri) and [ra](https://github.com/rabbitmq/ra) subsystems.
## Motivation
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.
## Features
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.
### Core Event Store Functionality
#### Event Stream Management
- **Stream Creation**: Automatic stream creation on first event append
- **Event Appending**: Atomic append operations with optimistic concurrency control
- **Event Retrieval**: Query events with forward/backward traversal support
- **Stream Versioning**: Track stream versions for conflict detection and resolution
- **Stream Listing**: Enumerate all streams in the store
#### Event Storage
- **Persistent Storage**: Durable event storage using Khepri's distributed key-value store
- **ACID Compliance**: Atomic, consistent, isolated, and durable operations
- **Conflict Resolution**: Built-in optimistic concurrency control
- **Data Integrity**: Checksum validation and corruption detection
#### Subscription System
- **Multiple Subscription Types**:
- `: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 filtering
- **Persistent Subscriptions**: Durable subscriptions that survive node restarts
- **Transient Subscriptions**: Temporary subscriptions for real-time processing
- **Event Replay**: Start subscriptions from any stream version
- **Acknowledgment System**: Reliable event delivery with ACK/NACK support
- **"Follow-the-Leader"**: Subscription processes automatically migrate to cluster leader
#### Snapshot Management
- **Aggregate Snapshots**: Store and retrieve aggregate state snapshots
- **Version-based Snapshots**: Snapshots tied to specific stream versions
- **Snapshot Lifecycle**: Create, read, update, and delete snapshot operations
- **Performance Optimization**: Reduce replay time for large aggregates
- **Distributed Storage**: Snapshots stored across the cluster for availability
### Distributed Architecture & Clustering
#### LibCluster Integration
ExESDB uses LibCluster for automatic cluster discovery and formation:
- **Strategy**: Gossip-based multicast discovery
- **Protocol**: UDP multicast on configurable port (default: 45892)
- **Network**: Automatic node discovery on shared networks
- **Security**: Shared secret authentication for cluster membership
- **Broadcast Discovery**: Configurable multicast addressing
#### Cluster Formation Process
1. **Initialization**: Node starts and initializes LibCluster topology
2. **Discovery**: Uses gossip multicast to discover peer nodes
3. **Authentication**: Validates cluster membership using shared secrets
4. **Coordination**: ClusterCoordinator manages join/leave operations
5. **Consensus**: Khepri cluster formation using Raft consensus
6. **Monitoring**: Continuous health monitoring and leader election
#### High Availability Features
- **Automatic Clustering**: Nodes automatically discover and join clusters
- **Split-Brain Prevention**: ClusterCoordinator prevents network partition issues
- **Leader Election**: Automatic leader election using Raft consensus
- **Failover**: Seamless handling of node failures
- **Data Replication**: Events replicated across cluster nodes
- **Consensus Protocol**: Ra/Raft ensures data consistency
### Storage Engine
#### Khepri Integration
- **Distributed Tree Store**: Hierarchical key-value storage
- **MVCC**: Multi-version concurrency control
- **Transactions**: ACID transaction support
- **Schema Evolution**: Support for data structure changes
- **Triggers**: Event-driven data processing
#### Ra (Raft) Consensus
- **Strong Consistency**: Linearizable read/write operations
- **Partition Tolerance**: Operates correctly during network partitions
- **Leader-based Replication**: Single leader for write operations
- **Log Compaction**: Automatic cleanup of old log entries
- **Snapshot Support**: Efficient state transfer for new nodes
### Configuration & Deployment
#### Environment Configuration
- `EX_ESDB_STORE_ID`: Unique identifier for the store instance
- `EX_ESDB_DB_TYPE`: Deployment type (`:single` or `:cluster`)
- `EX_ESDB_DATA_DIR`: Data directory for persistent storage
- `EX_ESDB_TIMEOUT`: Operation timeout configuration
- `EX_ESDB_CLUSTER_SECRET`: Shared secret for cluster authentication
- `EX_ESDB_COOKIE`: Erlang distribution cookie
- `EX_ESDB_PUB_SUB`: PubSub configuration for event broadcasting
#### LibCluster Configuration
```elixir
config :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")
]
]
]
```
### Gateway API Integration
#### High-Availability Proxy
- **Load Balancing**: Distribute requests across gateway workers
- **Service Discovery**: Automatic discovery of available gateway workers
- **Fault Tolerance**: Handle worker failures gracefully
- **Request Routing**: Smart routing based on operation type
#### Worker Distribution
- **Swarm Integration**: Distributed worker management
- **Process Migration**: Workers can move between cluster nodes
- **Resource Management**: Efficient resource utilization across cluster
- **Monitoring**: Real-time worker health and performance tracking
### Operational Features
#### Monitoring & Observability
- **Cluster Status**: Real-time cluster membership and health
- **Leader Tracking**: Monitor current cluster leader
- **Performance Metrics**: Operation latency and throughput
- **Error Tracking**: Comprehensive error logging and reporting
- **Health Checks**: Built-in health check endpoints
#### Development Tools
- **Cluster Manager**: Interactive cluster management script
- **Docker Compose**: Multi-node development environment
- **Chaos Engineering**: Built-in chaos testing capabilities
- **Validation Scripts**: Automated cluster validation tools
### Network Topology
```
┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐
│ 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
```
### Deployment Scenarios
#### Single Node Deployment
- **Development**: Local development and testing
- **Small Applications**: Simple event sourcing needs
- **Embedded Usage**: Integration within existing applications
#### Multi-Node Cluster
- **Production**: High-availability production deployments
- **Horizontal Scaling**: Scale read/write capacity
- **Geographic Distribution**: Multi-region deployments
- **Fault Tolerance**: Survive individual node failures
#### Container Orchestration
- **Docker Compose**: Development and testing environments
- **Kubernetes**: Production container orchestration
- **Docker Swarm**: Simplified container clustering
- **Health Checks**: Container-level health monitoring
### Performance Characteristics
#### Throughput
- **Write Performance**: Optimized for high-volume event appending
- **Read Performance**: Efficient event retrieval and streaming
- **Concurrent Operations**: Handle multiple simultaneous operations
- **Batch Processing**: Support for batch event operations
#### Scalability
- **Horizontal Scaling**: Add nodes to increase capacity
- **Storage Scalability**: Distributed storage across cluster
- **Subscription Scaling**: Distribute subscription load
- **Resource Utilization**: Efficient use of available resources
### Integration Capabilities
#### BEAM Ecosystem
- **Phoenix Integration**: Real-time web applications
- **LiveView Support**: Real-time UI updates
- **GenServer Integration**: Native BEAM process integration
- **OTP Supervision**: Fault-tolerant supervision trees
#### External Systems
- **REST APIs**: HTTP-based integration
- **Message Queues**: Integration with external queuing systems
- **Databases**: Projection and read model support
- **Monitoring Systems**: Metrics and alerting integration
## Installation
### Docker Installation
ExESDB is available as a Docker image on Docker Hub with automatic versioning based on the `mix.exs` version.
#### Available Tags
- `beamcampus/ex_esdb:latest` - Latest build from master branch
- `beamcampus/ex_esdb:0.0.18` - Specific version (current version)
- `beamcampus/ex_esdb:0.0.x` - Any specific version tag
#### Quick Start
**Single Node:**
```bash
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:**
```bash
# 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
```
#### Docker Compose
For development and testing, use the provided Docker Compose setup:
```bash
# 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:
- **Core Cluster**: 3-node ExESDB cluster (ex-esdb0, ex-esdb1, ex-esdb2)
- **Extended Tier**: Additional 2 nodes (ex-esdb10, ex-esdb11)
- **Massive Tier**: Additional 8 nodes (ex-esdb20-27)
- **Automatic Networking**: Configured Docker networks for cluster communication
- **Data Persistence**: Named volumes for data persistence
- **Health Checks**: Built-in container health monitoring
#### Environment Variables
> **📌 Important**: When using the dev-env Docker Compose configurations, you must export the `EX_ESDB_COOKIE` environment variable on your host machine. This single environment variable is used for all cluster authentication purposes (cookies, secrets, etc.).
>
> ```bash
> 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 |
#### Ports
| Port | Protocol | Description |
|------|----------|-------------|
| `4369` | TCP | EPMD (Erlang Port Mapper Daemon) |
| `9000-9100` | TCP | Erlang distribution ports |
| `45892` | UDP | LibCluster gossip multicast |
#### Health Checks
The Docker image includes a built-in health check script:
```bash
# Check container health
docker exec ex-esdb ./check-ex-esdb.sh
# View health status
docker inspect --format='{{.State.Health.Status}}' ex-esdb
```
#### Production Considerations
1. **Security**: Use strong, unique values for `EX_ESDB_CLUSTER_SECRET` and `EX_ESDB_COOKIE`
2. **Networking**: Ensure proper firewall rules for cluster communication
3. **Storage**: Use named volumes or bind mounts for data persistence
4. **Monitoring**: Implement external monitoring for cluster health
5. **Backups**: Regular backup of data volumes
6. **Resource Limits**: Set appropriate CPU and memory limits
### Hex Installation
ExESDB is also available as a Hex package for direct integration:
```elixir
def deps do
[
{:ex_esdb, "~> 0.0.18"}
]
end
```
## Contents
- [Getting Started](system/guides/getting_started.md)
## Releases
- [On Hex](https://hex.pm/packages/ex_esdb)
- [Release Documentation](https://hexdocs.pm/ex_esdb/index.html)