Derive a postgres client to database API specified by servant-db

Latest on Hackage:

This package is not currently in any snapshots. If you're interested in using it, we recommend adding it to Stackage Nightly. Doing so will make builds more reliable, and allow to host generated Haddocks.

BSD3 licensed by Anton Gushcha
Maintained by


Automatic derive of typed DB API based on postgresql-query package.

How to use:

  • Define your instances of MonadLogger and HasPostgres for your app monad:

newtype PostgresM a = PostgresM { runPostgresM :: PgMonadT (LoggingT IO) a }
  deriving (Functor, HasPostgres, MonadLogger, Monad, Applicative, MonadBase IO)
  • Define type level API:

type UserId = Int

data RegisterUser = RegisterUser {
  userRegName     :: String
, userRegPassword :: String
, userRegRegTime  :: Day
} deriving (Eq)

deriveToRow ''RegisterUser

data User = User {
  userId       :: UserId
, userName     :: String
, userPassword :: String
, userRegTime  :: Day
} deriving (Eq)

deriveFromRow ''User
deriveToRow ''User

type UserAPI =
       ArgNamed "u" (Composite RegisterUser)
    :> Procedure "postUser" (Only Int)
  :<|> ArgPos Int
    :> Procedure "getUser" (Maybe User)
  :<|> ArgPos Int
    :> Procedure "deleteUser" ()
  :<|> Procedure "getUsers" [User]
  • Derive client functions from the API:

postUser :: Composite RegisterUser -> PostgresM (Only Int)
getUser :: Int -> PostgresM (Maybe User)
deleteUser :: Int -> PostgresM ()
getUsers :: PostgresM [User]
(      postUser
  :<|> getUser
  :<|> deleteUser
  :<|> getUsers) = deriveDB (Proxy :: Proxy UserAPI) (Proxy :: Proxy PostgresM)
  • Use them. The full example you can view at example01/Main.hs module. And to compile it run the:

stack build --flag servant-db-postgresql:examples


  • Call functions in schema with :> operator:

type API = "test" :> ArgPos Int :> Procedure "square" (Only Int)

That will call function test.square(int).

  • Composite types are defined with Composite a wrapper:

type API = ArgNamed "u" (Composite UserCreate) :> Procedure "postUser" (Only Int)
  • Support for arrays:

type API = ArgPos (PGArray Int) :> Procedure "mleast" (Maybe (Only Int))
  • Support for variadic arguments:

type API = ArgPos (Variadic Int) :> Procedure "mleast" (Maybe (Only Int))
  • Support for default arguments with newypte Default a = Default (Maybe a):

type API = ArgPos (Default Int) :> Procedure "foo" (Only Int)


  • Push version for postgresql-query.

  • Make instance FromRow => FromRow (Maybe a) overlappable.

  • Fix haddocks for code blocks.

  • Split Arg to ArgNamed and ArgPos.

  • Initial release.
comments powered byDisqus