libraryDependencies += "dev.hnaderi" %% "edomata-doobie" % "0.12.0"

or for integrated modules:

libraryDependencies += "dev.hnaderi" %% "edomata-doobie-circe" % "0.12.0"
libraryDependencies += "dev.hnaderi" %% "edomata-doobie-upickle" % "0.12.0"

Note that doobie is built on top of JDBC which can't be used in javascript obviously, and this packages are available for JVM only.


import edomata.doobie.*

Defining codecs

when event sourcing:

given BackendCodec[Event] = CirceCodec.jsonb // or .json
given BackendCodec[Notification] = CirceCodec.jsonb

when using cqrs style:

given BackendCodec[State] = CirceCodec.jsonb 

Persisted snapshots (event sourcing only)

if you want to use persisted snapshots, you need to provide codec for your state model too.

given BackendCodec[State] = CirceCodec.jsonb 

Compiling application to a service

You need to use a driver to build your backend, there are two doobie drivers available:

  1. DoobieDriver event sourcing driver
  2. DoobieCQRSDriver cqrs driver
val app  = ??? // your application from previous chapter
val trx : Transactor[IO] = ??? // create your Transactor

val buildBackend = Backend
  .builder(AccountService)               // 1
  .use(DoobieDriver("domainname", trx))  // 2
  // .persistedSnapshot(maxInMem = 200)  // 3
  .withRetryConfig(retryInitialDelay = 2.seconds)

val application = buildBackend.use { backend =>
  val service = backend.compile(app)
  // compiling your application will give you a function
  // that takes a messages and does everything required,
  // and returns result.

    CommandMessage("abc",, "a", "receive")
  1. use your domain as described in previous chapter.
  2. domainname is used as schema name in postgres.
  3. feel free to navigate available options in backend builder.