# EventStore

CQRS event store implemented in Elixir. Uses [PostgreSQL]( (v9.5 or later) as the underlying storage engine.

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


MIT License

[![Build Status](](


### Overview

- [Getting started](guides/
- [Using the EventStore](guides/
  - [Writing to a stream](guides/
  - [Reading from a stream](guides/
  - [Reading from all streams](guides/
  - [Stream from all streams](guides/
  - [Subscribe to streams](guides/
    - [Ack received events](guides/
    - [Example subscriber](guides/
- [Running on a cluster](guides/
- [Event serialization](guides/
  - [Example JSON serializer](guides/
- [Upgrading an EventStore](guides/
- [Used in production?](#used-in-production)
- [Backup and administration](#backup-and-administration)
- [Benchmarking performance](#benchmarking-performance)
- [Contributing](#contributing)
  - [Contributors](#contributors)
- [Need help?](#need-help)


## Example usage

Append events to a stream:

stream_uuid = UUID.uuid4()
expected_version = 0
events = [
    event_type: "Elixir.ExampleEvent",
    data: %ExampleEvent{key: "value"},
    metadata: %{user: ""},

: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](guides/

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)

More: [Subscribe to streams](guides/

## 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:

- [Backup and restore](
- [Continuous archiving and Point-in-Time Recovery (PITR)](

## 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

- [Andrey Akulov](
- [Craig Savolainen](
- [David Soff](
- [Jan Vereecken](
- [Olafur Arason](
- [Paul Iannazzo](
- [Simon Harris](
- [Stuart Corbishley](

## Need help?

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

For commercial support, and consultancy, please contact [Ben Smith](