BSD-3-Clause licensed by Yorick Laupa
Maintained by [email protected]
This version can be pinned in stack with:eventstore-,5843

Module documentation for

EventStore Haskell TCP client

Join the chat at Build Status

That driver supports:

  • Read event(s) from regular or $all stream (forward or backward).
  • Write event(s) to regular stream.
  • Delete regular stream.
  • Transactional writes to regular stream.
  • Volatile subscriptions to regular or $all stream.
  • Catch-up subscriptions to regular or $all stream.
  • Competing consumers (a.k.a Persistent subscriptions) to regular stream.
  • Authenticated communication with EventStore server.
  • Read stream metadata (ACL and custom properties).
  • Write stream metadata (ACL and custom properties).
  • Cluster Connection.

Not implemented yet

  • Secured connection with the server (SSL).


  • GHC >= 7.8.3
  • Cabal >= 1.18
  • EventStore >= 3.0.0 (>= 3.1.0 if you want competing consumers)


$ cabal update
$ cabal install eventstore
  • From source
$ git clone
$ cd eventstore
$ cabal install --only-dependencies
$ cabal configure
$ cabal install

How to test

Tests are available. Those assume a server is running on and 1113 port.

$ cabal install --only-dependencies --enable-tests
$ cabal configure --enable-tests
$ cabal test

How to use

{-# LANGUAGE OverloadedStrings #-} -- That library uses `Text` pervasively. This pragma permits to use
                                   -- String literal when a Text is needed.
module Main where

import Data.Aeson
-- It requires to have `aeson` package installed. Note that EventStore doesn't constraint you to JSON
-- format but putting common use aside, by doing so you'll be able to use some interesting EventStore
-- features like its Complex Event Processing (CEP) capabality.

import Database.EventStore
-- Note that import also re-exports 'Control.Concurrent.Async' module, allowing the use of 'wait'
-- function for instance. There are also 'NonEmpty' data constructor and 'nonEmpty' function from
-- 'Data.List.NonEmpty'.

main :: IO ()
main = do
    -- A common pattern with an EventStore connection is to create a single instance only and pass it
    -- wherever you need it (it's threadsafe). It's very important to not consider an EventStore connection like
    -- its regular SQL counterpart. An EventStore connection will try its best to reconnect
    -- automatically to the server if the connection dropped. Of course that behavior can be tuned
    -- through some settings.
    conn <- connect defaultSettings (Static "" 1113)
    let js  = "isHaskellTheBest" .= True -- (.=) comes from Data.Aeson module.
        evt = createEvent "programming" Nothing (withJson js)

    -- Appends an event to a stream named `languages`.
    as <- sendEvent conn "languages" anyVersion evt

    -- EventStore interactions are fundamentally asynchronous. Nothing requires you to wait
    -- for the completion of an operation, but it's good to know if something went wrong.
    _ <- wait as

    -- Again, if you decide to `shutdown` an EventStore connection, it means your application is
    -- about to terminate.
    shutdown conn

    -- Make sure the EventStore connection completes every ongoing operation. For instance, if
    -- at the moment we call `shutdown` and some operations (or subscriptions) were still pending,
    -- the connection aborted all of them.
    waitTillClosed conn


That library was tested on Linux and OSX Yosemite.

Contributions and bug reports are welcome!

BSD3 License

-Yorick Laupa


  • Quit using internal .NET TimeSpan for dotnet-timespan TimeSpan

  • Implement Cluster connection.
  • Domain can be used to connect to a server instance.

  • Bump aeson version.

  • Bump async version.

  • Fix $maxAge and $cacheControl TimeSpan metadata serialization.
  • Fix timeSpanFrom* functions.
  • Implement timeSpanTotalDays, timeSpanTotalHours, timeSpanTotalMinutes and timeSpanTotalSeconds.
  • Add withBinary and withBinaryAndMetadata.
  • Remove useless TimeSpan ToJSON and FromJSON instances.
  • Drop attoparsec dependency.

  • Increase cereal upper bound to <0.6

  • Increase aeson upper bound to <0.11

  • Fix stackage integration.

  • Introduce convinient persistent subscription functions.
  • Add multi GHC version testing.

  • Rewrite entirely the internals.
  • Implement integration tests.
  • Rename every ExpectedVersion smart constructors.
  • Improve internal and public documentation.
  • Improve failure reports when the connection dropped.
  • Implement more robust internal connection.

  • Implement competing consumers.
  • Expose an uniform API among all kind of subscriptions.
  • Rewrite internal subscription management.
  • Add missing Eq or Show instances for exposed datatypes.
  • Add streamMetadataCustomPropertyValue and streamMetadataCustomProperty.
  • Add logging capability.

  • Fix compilation issue

  • Add setStreamMetadata
  • Add getStreamMetadata

  • Internal connection changes
  • Allow creating an event with an existing ID

  • Tight package channnel to connection instance in order to prevent loss on connection drops.
  • Connection has asynchronous operation for real now.

  • Fix date conversion. recordedEventCreateEpoch is no longer exposed.
  • Add waitTillCatchup and hasCaughtUp functions.
  • Add exactStream ExpectedVersion smart constructor. As the result, ExpectedVersion constructors are no longer exposed. You have to use anyStream, noStream, emptyStream or exactStream instead.

No changes

  • Support keepRetrying reconnection strategy.