EventStore

CQRS event store implemented in Elixir. Uses PostgreSQL as the underlying storage engine.

Requires Elixir v1.5 and PostgreSQL v9.5 or newer.

EventStore supports running on a cluster of nodes (since v0.11). Stream processes will be distributed amongst all available nodes, events are published to subscribers running on any node.

Changelog

MIT License

Build Status


Overview


Example usage

Append events to a stream:

stream_uuid = UUID.uuid4()
expected_version = 0
events = [
%EventStore.EventData{
event_type: "Elixir.ExampleEvent",
data: %ExampleEvent{key: "value"},
metadata: %{user: "someuser@example.com"},
}
]
:ok = EventStore.append_to_stream(stream_uuid, expected_version, events)

Read all events from a single stream, starting at the stream's first event:

{:ok, events} = EventStore.read_stream_forward(stream_uuid)

More: Using the EventStore

Subscribe to events appended to all streams:

{:ok, subscription} = EventStore.subscribe_to_all_streams("example_subscription", self())
receive do
{:events, events} ->
# ... process events & ack receipt
EventStore.ack(subscription, events)
end

More: Subscribe to streams

Used in production?

Yes, this event store is being used in production.

PostgreSQL is used for the underlying storage. Providing guarantees to store data securely. It is ACID-compliant and transactional. PostgreSQL has a proven architecture. A strong reputation for reliability, data integrity, and correctness.

Backup and administration

You can use any standard PostgreSQL tool to manage the event store data:

Benchmarking performance

Run the benchmark suite using mix with the bench environment, as configured in config/bench.exs. Logging is disabled for benchmarking.

$ MIX_ENV=bench mix do es.reset, app.start, bench

Example output:

## AppendEventsBench
append events, single writer 100 10170.26 µs/op
append events, 10 concurrent writers 20 85438.80 µs/op
append events, 100 concurrent writers 2 1102006.00 µs/op
## ReadEventsBench
read events, single reader 1000 1578.10 µs/op
read events, 10 concurrent readers 100 16799.80 µs/op
read events, 100 concurrent readers 10 167397.30 µs/op

Contributing

Pull requests to contribute new or improved features, and extend documentation are most welcome.

Please follow the existing coding conventions, or refer to the Elixir style guide.

You should include unit tests to cover any changes.

Contributors

Need help?

Please open an issue if you encounter a problem, or need assistance.

For commercial support, and consultancy, please contact Ben Smith.