commanded_eventsourcingdb_adapter

An Elixir event store adapter that integrates Commanded with EventSourcingDB – a purpose-built database for event sourcing.

Documentation:

Supported Features

Installation

The package can be installed by adding commanded_eventsourcingdb_adapter to your list of dependencies in mix.exs:

def deps do
[
{:commanded_eventsourcingdb_adapter, "~> 0.0.1"}
]
end

Configuration

Configure the adapter in your application config:

# config/config.exs
config :my_app, MyApp,
event_store: [
adapter: Commanded.EventStore.Adapters.EventSourcingDB,
client: [
api_token: "your-api-token",
base_url: "http://localhost:3000"
],
stream_prefix: "myapp",
source: "https://my.app"
]

Configuration Options

CloudEvents

Commanded has its own internal event representation as RecordedEvent whereas EventSourcingDB follows the CloudEvents specification. The adapter maps between the two as described in ADR 0001.

Event Source

Define in your config, see above.

Event ID

The event ID within commanded's RecordedEvent is a concatenation of the source + event id from ESDB: #{event.source}/#{event.id}

Event Types

Commanded has a default type provider, that (de)serializes your module name as event type. In the example below, the event has Elixir.AccountOpened as event type. This is perhaps not the best value for your event type, consider your custom type provider for naming your events types.

Event Subject

Commanded is stream-oriented, which translates to subjects as per CloudEvents spec, ADR 0002 specifies the used semantics.

The subject: /#{stream_prefix}/#{identity_prefix}/#{aggregate_uuid}

Metadata Storage

Commanded stores correlation_id, causation_id, and metadata as part of the event's data field using a special __commanded_metadata__ key:

# Data field stored in ESDB
%{
"__commanded_metadata__" => %{
"correlation_id" => "uuid-string",
"causation_id" => "uuid-string",
"metadata" => %{"key" => "value"}
},
# ... event data fields
}

Sample CloudEvent

This is what an event looks like when stored in EventSourcingDB:

{
"specversion": "1.0",
"id": "5",
"source": "https://my.app",
"subject": "/myapp/bank-account/ACC123",
"type": "Elixir.AccountOpened",
"datacontenttype": "application/json",
"data": {
"__commanded_metadata__": {
"correlation_id": "aaa-bbb-ccc",
"causation_id": "ddd-eee-fff",
"metadata": {}
},
"account_number": "ACC123",
"initial_balance": 1000
},
"time": "2025-04-15T10:00:00Z",
"predecessorhash": "0000000000000000000000000000000000000000000000000000000000000000",
"hash": "abc123..."
}

Testing

Run tests using:

mix test

Tests use Testcontainers to spin up an EventSourcingDB instance.