diff --git a/CHANGELOG.md b/CHANGELOG.md
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -7,6 +7,16 @@
 
 ## [Unreleased]
 
+## [0.2.0.0] - 22.09.2026
+
+### Changed
+- Dynamic `PostgreSQL` effect in [#15](https://github.com/fpringle/effectful-postgresql/pull/15)
+
+### Added
+
+- Support `withTransactionX` functions from `postgresql-simple` in [#13](https://github.com/fpringle/effectful-postgresql/pulls/13)
+- Support OpenTelemetry instrumentation in [#16](https://github.com/fpringle/effectful-postgresql/pull/16)
+
 ## [0.1.0.1] - 04.08.2025
 
 ### Changed
@@ -22,6 +32,7 @@
 - Reasonably detailed READMEs
 - CI that builds and tests the packages for each version of GHC in the `tested-with` field.
 
-[unreleased]: https://github.com/fpringle/effectful-postgresql/compare/v0.1.0.1...HEAD
-[0.1.0.1]: https://github.com/fpringle/effectful-postgresql/releases/tag/v0.1.0.1
+[unreleased]: https://github.com/fpringle/effectful-postgresql/compare/effectful-postgresql-0.2.0.0...HEAD
+[0.2.0.0]: https://github.com/fpringle/effectful-postgresql/compare/v0.1.0.1...effectful-postgresql-0.2.0.0
+[0.1.0.1]: https://github.com/fpringle/effectful-postgresql/compare/v0.1.0.0...v0.1.0.1
 [0.1.0.0]: https://github.com/fpringle/effectful-postgresql/releases/tag/v0.1.0.0
diff --git a/README.md b/README.md
--- a/README.md
+++ b/README.md
@@ -1,8 +1,10 @@
 # effectful-postgresql
 
-This package provides an `effectful` effect for [postgresql-simple](https://hackage.haskell.org/package/postgresql-simple)'s `Connection` type.
+This package provides `effectful` effects for using [postgresql-simple](https://hackage.haskell.org/package/postgresql-simple)'s `Connection` type.
 
-It defines a dynamic effect to allow effectful functions to use a `Connection`, without worrying about where that `Connection` comes from.
+It defines:
+- a dynamic `WithConnection` effect to allow effectful functions to use a `Connection`, without worrying about where that `Connection` comes from.
+- a dynamic `PostgreSQL` effect ro run database operations from `postgresql-simple`.
 
 For a higher-level effect library using [Opaleye](https://hackage.haskell.org/package/opaleye), see [effectful-opaleye](https://github.com/fpringle/effectful-postgresql/blob/main/effectful-opaleye#readme).
 
@@ -15,20 +17,19 @@
 import Effectful.PostgreSQL as EP
 import qualified Database.PostgreSQL.Simple as PSQL
 
-insertAndList :: (EP.WithConnection :> es, IOE :> es) => Eff es [User]
+insertAndList :: (WithConnection :> es, IOE :> es) => Eff es [User]
 insertAndList = EP.withConnection $ \conn -> do
-  PSQL.execute conn "insert into users (first_name) values (?)" ["Nuala"]
-  PSQL.query conn "select * from users where first_name in ?" $ Only $ In ["Anna", "Boris", "Carla"]
+  liftIO $ PSQL.execute conn "insert into users (first_name) values (?)" ["Nuala"]
+  liftIO $ PSQL.query conn "select * from users where first_name in ?" $ Only $ In ["Anna", "Boris", "Carla"]
 ```
 
-In fact, for convenience we also define lifted versions of all of the query/execute
-functions from `postgresql-simple`, so we can completely forget about `Connection` and rewrite the above to:
+The `PostgreSQL` effect lets us completely forget about `Connection` and rewrite the above to:
 
 ```haskell
 
 import Effectful.PostgreSQL
 
-insertAndList :: (EP.WithConnection :> es, IOE :> es) => Eff es [User]
+insertAndList :: (PostgreSQL :> es) => Eff es [User]
 insertAndList = do
   EP.execute "insert into users (first_name) values (?)" ["Nuala"]
   EP.query "select * from users where first_name in ?" $ Only $ In ["Anna", "Boris", "Carla"]
@@ -38,19 +39,33 @@
 
 ```haskell
 -- use a transaction
-insertAndListCarefully :: (EP.WithConnection :> es, IOE :> es) => Eff es [User]
+insertAndListCarefully :: (PostgreSQL :> es) => Eff es [User]
 insertAndListCarefully = EP.withTransaction insertAndList
 
 -- stream + fold over results (in Eff)
-countUsersIneffeciently :: (EP.WithConnection :> es, IOE :> es, Log :> es) => Eff es Int
+countUsersIneffeciently :: (PostgreSQL :> es, Log :> es) => Eff es Int
 countUsersIneffeciently =
-  EP.fold_ "select * from users" 0 $ \acc row ->
+  EP.fold_ "select * from users" 0 $ \acc row -> do
     log $ "User: " <> show row
     pure $ acc + 1
 ```
 
 ## Interpreters
 
+In order to discharge the `PostgreSQL` effect we use the `WithConnection` effect:
+
+```haskell
+dischargePostgreSQL :: (WithConnection :> es, IOE :> es) => Eff es [User]
+dischargePostgreSQL = runPostgreSQL insertAndListCarefully
+```
+
+Alternatively we can use the OpenTelemetry support provided by [hs-opentelemetry-instrumentation-postgresql-simple](https://hackage-content.haskell.org/package/hs-opentelemetry-instrumentation-postgresql-simple/docs/OpenTelemetry-Instrumentation-PostgresqlSimple.html) (note that this requires enabling the `enable-opentel` cabal flag):
+
+```haskell
+dischargePostgreSQLUsingOpenTelemetry :: (WithConnection :> es, IOE :> es) => Eff es [User]
+dischargePostgreSQLUsingOpenTelemetry = runPostgreSQLOT insertAndListCarefully
+```
+
 The simplest way of running the `WithConnection` effect is by just providing a `Connection`, which we can get in the normal ways:
 
 ```haskell
@@ -59,12 +74,12 @@
 
 usingConnection :: IO ()
 usingConnection =
-  bracket (PSQL.connectPostgreSQL "") PSQL.close $ \conn ->
-    runEff . EP.runWithconnection conn $ insertAndListCarefully
+  void $ bracket (PSQL.connectPostgreSQL "") PSQL.close $ \conn ->
+    runEff . runWithConnection conn $ runPostgreSQL insertAndListCarefully
 
 usingConnectInfo :: IO ()
 usingConnectInfo =
-    runEff . EP.runWithconnectInfo PSQL.defaultConnectInfo $ insertAndListCarefully
+    void . runEff . runWithConnectInfo PSQL.defaultConnectInfo $ runPostgreSQL insertAndListCarefully
 ```
 
 Alternatively, we can use a connection pool (from [resource-pool](https://hackage.haskell.org/package/resource-pool)
@@ -80,5 +95,5 @@
 usingConnectionPool = do
   poolCfg <- P.mkDefaultPoolConfig (PSQL.connectPostgreSQL "") PSQL.close 5.0 10
   pool <- P.newPool poolCfg
-  runEff . EP.runWithconnectionPool pool $ insertAndListCarefully
+  void . runEff . runWithConnectionPool pool $ runPostgreSQL insertAndListCarefully
 ```
diff --git a/effectful-postgresql.cabal b/effectful-postgresql.cabal
--- a/effectful-postgresql.cabal
+++ b/effectful-postgresql.cabal
@@ -1,6 +1,6 @@
 cabal-version:      3.0
 name:               effectful-postgresql
-version:            0.1.0.1
+version:            0.2.0.0
 synopsis:
   effectful support for mid-level PostgreSQL operations.
 description:
@@ -17,9 +17,7 @@
                     CHANGELOG.md
 
 tested-with:
-    GHC == 8.8.4
-  , GHC == 8.10.7
-  , GHC == 9.0.2
+    GHC == 9.0.2
   , GHC == 9.2.4
   , GHC == 9.2.8
   , GHC == 9.4.2
@@ -36,12 +34,21 @@
   default: True
   manual: False
 
+flag enable-otel
+  description: Enable OpenTelemetry instrumentation support using
+               hs-opentelemetry-instrumentation-postgresql-simple.
+  default: False
+  manual: True
+
 common warnings
   ghc-options: -Wall -Wno-unused-do-bind -Wunused-packages
 
   if flag(enable-pool)
     cpp-options: -DPOOL
 
+  if flag(enable-otel)
+    cpp-options: -DOTEL
+
 common deps
   build-depends:
     , base >= 4 && < 5
@@ -53,6 +60,10 @@
     build-depends:
       , unliftio-pool >= 0.4.1 && < 0.5
 
+  if flag(enable-otel)
+    build-depends:
+      , hs-opentelemetry-instrumentation-postgresql-simple >= 1.0 && < 1.1
+
 common extensions
   default-extensions:
     DataKinds
@@ -72,6 +83,7 @@
     , extensions
   exposed-modules:
       Effectful.PostgreSQL
+      Effectful.PostgreSQL.Effect
       Effectful.PostgreSQL.Connection
   if flag(enable-pool)
     exposed-modules:
diff --git a/src/Effectful/PostgreSQL.hs b/src/Effectful/PostgreSQL.hs
--- a/src/Effectful/PostgreSQL.hs
+++ b/src/Effectful/PostgreSQL.hs
@@ -1,9 +1,10 @@
 {-# LANGUAGE CPP #-}
 
 module Effectful.PostgreSQL
-  ( -- * Effect
+  ( -- * Effects
     WithConnection
   , withConnection
+  , PostgreSQL
 
     -- ** Interpreters
   , runWithConnection
@@ -12,6 +13,12 @@
   , runWithConnectionPool
 #endif
 
+  , runPostgreSQL
+
+#if OTEL
+  , runPostgreSQLOT
+#endif
+
     -- * Lifted versions of functions from Database.PostgreSQL.Simple
 
     -- ** Queries that return results
@@ -27,6 +34,15 @@
 
     -- ** Transaction handling
   , withTransaction
+  , withTransactionLevel
+  , PSQL.IsolationLevel (..)
+  , withTransactionMode
+  , PSQL.TransactionMode (..)
+  , PSQL.ReadWriteMode (..)
+  , withTransactionModeRetry
+  , withTransactionModeRetry'
+  , withTransactionSerializable
+  , withTransactionSerialisable
   , withSavepoint
   , begin
   , commit
@@ -47,272 +63,17 @@
   , forEachWith
   , forEachWith_
   , returningWith
+
+  -- ** Error predicates
+  , PSQL.isSerializationError
+  , PSQL.isNoActiveTransactionError
+  , PSQL.isFailedTransactionError
   )
 where
 
-import Data.Int (Int64)
-import qualified Database.PostgreSQL.Simple as PSQL
-import qualified Database.PostgreSQL.Simple.FromRow as PSQL
-import Effectful
+import qualified Database.PostgreSQL.Simple.Transaction as PSQL
 import Effectful.PostgreSQL.Connection as Conn
-import GHC.Stack
+import Effectful.PostgreSQL.Effect
 #if POOL
 import Effectful.PostgreSQL.Connection.Pool as Pool
 #endif
-
--- | Lifted 'PSQL.query'.
-query ::
-  (HasCallStack, WithConnection :> es, IOE :> es, PSQL.ToRow q, PSQL.FromRow r) =>
-  PSQL.Query ->
-  q ->
-  Eff es [r]
-query q row = withConnection $ \conn -> liftIO (PSQL.query conn q row)
-
--- | Lifted 'PSQL.query_'.
-query_ ::
-  (HasCallStack, WithConnection :> es, IOE :> es, PSQL.FromRow r) =>
-  PSQL.Query ->
-  Eff es [r]
-query_ row = withConnection $ \conn -> liftIO (PSQL.query_ conn row)
-
--- | Lifted 'PSQL.queryWith'.
-queryWith ::
-  (HasCallStack, WithConnection :> es, IOE :> es, PSQL.ToRow q) =>
-  PSQL.RowParser r ->
-  PSQL.Query ->
-  q ->
-  Eff es [r]
-queryWith parser q row =
-  withConnection $ \conn -> liftIO (PSQL.queryWith parser conn q row)
-
--- | Lifted 'PSQL.queryWith_'.
-queryWith_ ::
-  (HasCallStack, WithConnection :> es, IOE :> es) =>
-  PSQL.RowParser r ->
-  PSQL.Query ->
-  Eff es [r]
-queryWith_ parser row =
-  withConnection $ \conn -> liftIO (PSQL.queryWith_ parser conn row)
-
--- | Lifted 'PSQL.execute'.
-execute ::
-  (HasCallStack, WithConnection :> es, IOE :> es, PSQL.ToRow q) =>
-  PSQL.Query ->
-  q ->
-  Eff es Int64
-execute q row = withConnection $ \conn -> liftIO (PSQL.execute conn q row)
-
--- | Lifted 'PSQL.execute_'.
-execute_ ::
-  (HasCallStack, WithConnection :> es, IOE :> es) =>
-  PSQL.Query ->
-  Eff es Int64
-execute_ row = withConnection $ \conn -> liftIO (PSQL.execute_ conn row)
-
--- | Lifted 'PSQL.executeMany'.
-executeMany ::
-  (HasCallStack, WithConnection :> es, IOE :> es, PSQL.ToRow q) =>
-  PSQL.Query ->
-  [q] ->
-  Eff es Int64
-executeMany q rows = withConnection $ \conn -> liftIO (PSQL.executeMany conn q rows)
-
--- | Lifted 'PSQL.withTransaction'.
-withTransaction ::
-  (HasCallStack, WithConnection :> es, IOE :> es) => Eff es a -> Eff es a
-withTransaction f =
-  unliftWithConn $ \conn unlift ->
-    PSQL.withTransaction conn (unlift f)
-
--- | Lifted 'PSQL.withSavepoint'.
-withSavepoint :: (HasCallStack, WithConnection :> es, IOE :> es) => Eff es a -> Eff es a
-withSavepoint f =
-  unliftWithConn $ \conn unlift ->
-    PSQL.withSavepoint conn (unlift f)
-
--- | Lifted 'PSQL.begin'.
-begin :: (HasCallStack, WithConnection :> es, IOE :> es) => Eff es ()
-begin = withConnection $ liftIO . PSQL.begin
-
--- | Lifted 'PSQL.commit'.
-commit :: (HasCallStack, WithConnection :> es, IOE :> es) => Eff es ()
-commit = withConnection $ liftIO . PSQL.commit
-
--- | Lifted 'PSQL.rollback'.
-rollback :: (HasCallStack, WithConnection :> es, IOE :> es) => Eff es ()
-rollback = withConnection $ liftIO . PSQL.rollback
-
-(...) :: (a -> b) -> (t1 -> t2 -> a) -> t1 -> t2 -> b
-unlift ... f = \a' row -> unlift $ f a' row
-
-unliftWithConn ::
-  (HasCallStack, WithConnection :> es, IOE :> es) =>
-  (PSQL.Connection -> (forall b. Eff es b -> IO b) -> IO a) ->
-  Eff es a
-unliftWithConn f =
-  withConnection $ \conn ->
-    withSeqEffToIO $ \unlift ->
-      liftIO $ f conn unlift
-{-# INLINE unliftWithConn #-}
-
--- | Lifted 'PSQL.fold'.
-fold ::
-  (HasCallStack, WithConnection :> es, IOE :> es, PSQL.FromRow row, PSQL.ToRow params) =>
-  PSQL.Query ->
-  params ->
-  a ->
-  (a -> row -> Eff es a) ->
-  Eff es a
-fold q params a f =
-  unliftWithConn $ \conn unlift ->
-    PSQL.fold conn q params a (unlift ... f)
-
--- | Lifted 'PSQL.foldWithOptions'.
-foldWithOptions ::
-  (HasCallStack, WithConnection :> es, IOE :> es, PSQL.FromRow row, PSQL.ToRow params) =>
-  PSQL.FoldOptions ->
-  PSQL.Query ->
-  params ->
-  a ->
-  (a -> row -> Eff es a) ->
-  Eff es a
-foldWithOptions opts q params a f =
-  unliftWithConn $ \conn unlift ->
-    PSQL.foldWithOptions opts conn q params a (unlift ... f)
-
--- | Lifted 'PSQL.fold_'.
-fold_ ::
-  (HasCallStack, WithConnection :> es, IOE :> es, PSQL.FromRow row) =>
-  PSQL.Query ->
-  a ->
-  (a -> row -> Eff es a) ->
-  Eff es a
-fold_ q a f =
-  unliftWithConn $ \conn unlift ->
-    PSQL.fold_ conn q a (unlift ... f)
-
--- | Lifted 'PSQL.foldWithOptions_'.
-foldWithOptions_ ::
-  (HasCallStack, WithConnection :> es, IOE :> es, PSQL.FromRow row) =>
-  PSQL.FoldOptions ->
-  PSQL.Query ->
-  a ->
-  (a -> row -> Eff es a) ->
-  Eff es a
-foldWithOptions_ opts q a f =
-  unliftWithConn $ \conn unlift ->
-    PSQL.foldWithOptions_ opts conn q a (unlift ... f)
-
--- | Lifted 'PSQL.forEach'.
-forEach ::
-  (HasCallStack, WithConnection :> es, IOE :> es, PSQL.FromRow r, PSQL.ToRow q) =>
-  PSQL.Query ->
-  q ->
-  (r -> Eff es ()) ->
-  Eff es ()
-forEach q row forR =
-  unliftWithConn $ \conn unlift ->
-    PSQL.forEach conn q row (unlift . forR)
-
--- | Lifted 'PSQL.forEach_'.
-forEach_ ::
-  (HasCallStack, WithConnection :> es, IOE :> es, PSQL.FromRow r) =>
-  PSQL.Query ->
-  (r -> Eff es ()) ->
-  Eff es ()
-forEach_ q forR =
-  unliftWithConn $ \conn unlift ->
-    PSQL.forEach_ conn q (unlift . forR)
-
--- | Lifted 'PSQL.returning'.
-returning ::
-  (HasCallStack, WithConnection :> es, IOE :> es, PSQL.ToRow q, PSQL.FromRow r) =>
-  PSQL.Query ->
-  [q] ->
-  Eff es [r]
-returning q rows = withConnection $ \conn -> liftIO $ PSQL.returning conn q rows
-
--- | Lifted 'PSQL.foldWith'.
-foldWith ::
-  (HasCallStack, WithConnection :> es, IOE :> es, PSQL.ToRow params) =>
-  PSQL.RowParser row ->
-  PSQL.Query ->
-  params ->
-  a ->
-  (a -> row -> Eff es a) ->
-  Eff es a
-foldWith parser q params a f =
-  unliftWithConn $ \conn unlift ->
-    PSQL.foldWith parser conn q params a (unlift ... f)
-
--- | Lifted 'PSQL.foldWithOptionsAndParser'.
-foldWithOptionsAndParser ::
-  (HasCallStack, WithConnection :> es, IOE :> es, PSQL.ToRow params) =>
-  PSQL.FoldOptions ->
-  PSQL.RowParser row ->
-  PSQL.Query ->
-  params ->
-  a ->
-  (a -> row -> Eff es a) ->
-  Eff es a
-foldWithOptionsAndParser opts parser q params a f =
-  unliftWithConn $ \conn unlift ->
-    PSQL.foldWithOptionsAndParser opts parser conn q params a (unlift ... f)
-
--- | Lifted 'PSQL.foldWith_'.
-foldWith_ ::
-  (HasCallStack, WithConnection :> es, IOE :> es) =>
-  PSQL.RowParser row ->
-  PSQL.Query ->
-  a ->
-  (a -> row -> Eff es a) ->
-  Eff es a
-foldWith_ parser q a f =
-  unliftWithConn $ \conn unlift ->
-    PSQL.foldWith_ parser conn q a (unlift ... f)
-
--- | Lifted 'PSQL.foldWithOptionsAndParser_'.
-foldWithOptionsAndParser_ ::
-  (HasCallStack, WithConnection :> es, IOE :> es) =>
-  PSQL.FoldOptions ->
-  PSQL.RowParser row ->
-  PSQL.Query ->
-  a ->
-  (a -> row -> Eff es a) ->
-  Eff es a
-foldWithOptionsAndParser_ opts parser q a f =
-  unliftWithConn $ \conn unlift ->
-    PSQL.foldWithOptionsAndParser_ opts parser conn q a (unlift ... f)
-
--- | Lifted 'PSQL.forEachWith'.
-forEachWith ::
-  (HasCallStack, WithConnection :> es, IOE :> es, PSQL.ToRow q) =>
-  PSQL.RowParser r ->
-  PSQL.Query ->
-  q ->
-  (r -> Eff es ()) ->
-  Eff es ()
-forEachWith parser q row forR =
-  unliftWithConn $ \conn unlift ->
-    PSQL.forEachWith parser conn q row (unlift . forR)
-
--- | Lifted 'PSQL.forEachWith_'.
-forEachWith_ ::
-  (HasCallStack, WithConnection :> es, IOE :> es) =>
-  PSQL.RowParser r ->
-  PSQL.Query ->
-  (r -> Eff es ()) ->
-  Eff es ()
-forEachWith_ parser row forR =
-  unliftWithConn $ \conn unlift ->
-    PSQL.forEachWith_ parser conn row (unlift . forR)
-
--- | Lifted 'PSQL.returningWith'.
-returningWith ::
-  (HasCallStack, WithConnection :> es, IOE :> es, PSQL.ToRow q) =>
-  PSQL.RowParser r ->
-  PSQL.Query ->
-  [q] ->
-  Eff es [r]
-returningWith parser q rows =
-  withConnection $ \conn -> liftIO $ PSQL.returningWith parser conn q rows
diff --git a/src/Effectful/PostgreSQL/Effect.hs b/src/Effectful/PostgreSQL/Effect.hs
new file mode 100644
--- /dev/null
+++ b/src/Effectful/PostgreSQL/Effect.hs
@@ -0,0 +1,374 @@
+{-# LANGUAGE CPP #-}
+{-# LANGUAGE PackageImports #-}
+{-# LANGUAGE TemplateHaskell #-}
+
+module Effectful.PostgreSQL.Effect
+  ( -- * Effect
+    PostgreSQL (..)
+
+    -- ** Interpreters
+  , runPostgreSQL
+#if OTEL
+  , runPostgreSQLOT
+#endif
+
+    -- * Lifted versions of functions from Database.PostgreSQL.Simple
+
+    -- ** Queries that return results
+  , query
+  , query_
+  , queryWith
+  , queryWith_
+
+    -- ** Statements that do not return results
+  , execute
+  , execute_
+  , executeMany
+
+    -- ** Transaction handling
+  , withTransaction
+  , withTransactionLevel
+  , PSQL.IsolationLevel (..)
+  , withTransactionMode
+  , PSQL.TransactionMode (..)
+  , PSQL.ReadWriteMode (..)
+  , withTransactionModeRetry
+  , withTransactionModeRetry'
+  , withTransactionSerializable
+  , withTransactionSerialisable
+  , withSavepoint
+  , begin
+  , commit
+  , rollback
+
+    -- ** Queries that stream results
+  , fold
+  , foldWithOptions
+  , fold_
+  , foldWithOptions_
+  , forEach
+  , forEach_
+  , returning
+  , foldWith
+  , foldWithOptionsAndParser
+  , foldWith_
+  , foldWithOptionsAndParser_
+  , forEachWith
+  , forEachWith_
+  , returningWith
+  )
+where
+
+import qualified Control.Exception as E
+import Data.Int (Int64)
+import qualified Database.PostgreSQL.Simple as PSQL
+import qualified Database.PostgreSQL.Simple.Transaction as PSQL
+import qualified Database.PostgreSQL.Simple.FromRow as PSQL
+import Effectful
+import Effectful.Dispatch.Dynamic
+import Effectful.PostgreSQL.Connection
+import Effectful.TH
+#if OTEL
+import qualified "hs-opentelemetry-instrumentation-postgresql-simple" OpenTelemetry.Instrumentation.PostgresqlSimple as OT
+#endif
+
+-- | Dynamic effect representing all the Postgres operations we want to perform.
+data PostgreSQL :: Effect where
+  -- | Lifted 'PSQL.query'.
+  Query :: (PSQL.ToRow q, PSQL.FromRow r) => PSQL.Query -> q -> PostgreSQL m [r]
+  -- | Lifted 'PSQL.queryWith'.
+  QueryWith :: (PSQL.ToRow q) => PSQL.RowParser r -> PSQL.Query -> q -> PostgreSQL m [r]
+  -- | Lifted 'PSQL.query_'.
+  Query_ :: (PSQL.FromRow r) => PSQL.Query -> PostgreSQL m [r]
+  -- | Lifted 'PSQL.queryWith_'.
+  QueryWith_ :: PSQL.RowParser r -> PSQL.Query -> PostgreSQL m [r]
+  --
+
+  -- | Lifted 'PSQL.execute'.
+  Execute :: (PSQL.ToRow q) => PSQL.Query -> q -> PostgreSQL m Int64
+  -- | Lifted 'PSQL.execute_'.
+  Execute_ :: PSQL.Query -> PostgreSQL m Int64
+  -- | Lifted 'PSQL.executeMany'.
+  ExecuteMany :: (PSQL.ToRow q) => PSQL.Query -> [q] -> PostgreSQL m Int64
+  --
+
+  -- | Lifted 'PSQL.withTransaction'.
+  WithTransaction :: m a -> PostgreSQL m a
+  -- | Lifted 'PSQL.withTransactionLevel'.
+  WithTransactionLevel :: PSQL.IsolationLevel -> m a -> PostgreSQL m a
+  -- | Lifted 'PSQL.withTransactionMode'.
+  WithTransactionMode :: PSQL.TransactionMode -> m a -> PostgreSQL m a
+  -- | Lifted 'PSQL.withTransactionModeRetry'.
+  WithTransactionModeRetry :: PSQL.TransactionMode -> (PSQL.SqlError -> Bool) -> m a -> PostgreSQL m a
+  -- | Lifted 'PSQL.withTransactionModeRetry''.
+  WithTransactionModeRetry' :: E.Exception e => PSQL.TransactionMode -> (e -> Bool) -> m a -> PostgreSQL m a
+  -- | Lifted 'PSQL.withTransactionSerializable'.
+  WithTransactionSerializable :: m a -> PostgreSQL m a
+  -- | Lifted 'PSQL.withSavepoint'.
+  WithSavepoint :: m a -> PostgreSQL m a
+  -- | Lifted 'PSQL.begin'.
+  Begin :: PostgreSQL m ()
+  -- | Lifted 'PSQL.commit'.
+  Commit :: PostgreSQL m ()
+  -- | Lifted 'PSQL.rollback'.
+  Rollback :: PostgreSQL m ()
+  --
+
+  -- | Lifted 'PSQL.fold'.
+  Fold ::
+    (PSQL.FromRow row, PSQL.ToRow params) =>
+    PSQL.Query ->
+    params ->
+    a ->
+    (a -> row -> m a) ->
+    PostgreSQL m a
+  -- | Lifted 'PSQL.fold_'.
+  Fold_ ::
+    (PSQL.FromRow row) =>
+    PSQL.Query ->
+    a ->
+    (a -> row -> m a) ->
+    PostgreSQL m a
+  -- | Lifted 'PSQL.foldWithOptions'.
+  FoldWithOptions ::
+    (PSQL.FromRow row, PSQL.ToRow params) =>
+    PSQL.FoldOptions ->
+    PSQL.Query ->
+    params ->
+    a ->
+    (a -> row -> m a) ->
+    PostgreSQL m a
+  -- | Lifted 'PSQL.foldWithOptions_'.
+  FoldWithOptions_ ::
+    (PSQL.FromRow row) =>
+    PSQL.FoldOptions ->
+    PSQL.Query ->
+    a ->
+    (a -> row -> m a) ->
+    PostgreSQL m a
+  -- | Lifted 'PSQL.forEach'.
+  ForEach ::
+    (PSQL.FromRow r, PSQL.ToRow q) =>
+    PSQL.Query ->
+    q ->
+    (r -> m ()) ->
+    PostgreSQL m ()
+  -- | Lifted 'PSQL.forEach_'.
+  ForEach_ ::
+    (PSQL.FromRow r) =>
+    PSQL.Query ->
+    (r -> m ()) ->
+    PostgreSQL m ()
+  -- | Lifted 'PSQL.returning'.
+  Returning :: (PSQL.ToRow q, PSQL.FromRow r) => PSQL.Query -> [q] -> PostgreSQL m [r]
+  -- | Lifted 'PSQL.foldWith'.
+  FoldWith ::
+    (PSQL.ToRow params) =>
+    PSQL.RowParser row ->
+    PSQL.Query ->
+    params ->
+    a ->
+    (a -> row -> m a) ->
+    PostgreSQL m a
+  -- | Lifted 'PSQL.foldWithOptionsAndParser'.
+  FoldWithOptionsAndParser ::
+    (PSQL.ToRow params) =>
+    PSQL.FoldOptions ->
+    PSQL.RowParser row ->
+    PSQL.Query ->
+    params ->
+    a ->
+    (a -> row -> m a) ->
+    PostgreSQL m a
+  -- | Lifted 'PSQL.foldWith_'.
+  FoldWith_ ::
+    () =>
+    PSQL.RowParser row ->
+    PSQL.Query ->
+    a ->
+    (a -> row -> m a) ->
+    PostgreSQL m a
+  -- | Lifted 'PSQL.foldWithOptionsAndParser_'.
+  FoldWithOptionsAndParser_ ::
+    () =>
+    PSQL.FoldOptions ->
+    PSQL.RowParser row ->
+    PSQL.Query ->
+    a ->
+    (a -> row -> m a) ->
+    PostgreSQL m a
+  -- | Lifted 'PSQL.forEachWith'.
+  ForEachWith ::
+    (PSQL.ToRow q) =>
+    PSQL.RowParser r ->
+    PSQL.Query ->
+    q ->
+    (r -> m ()) ->
+    PostgreSQL m ()
+  -- | Lifted 'PSQL.forEachWith_'.
+  ForEachWith_ ::
+    () =>
+    PSQL.RowParser r ->
+    PSQL.Query ->
+    (r -> m ()) ->
+    PostgreSQL m ()
+  -- | Lifted 'PSQL.returningWith'.
+  ReturningWith :: (PSQL.ToRow q) => PSQL.RowParser r -> PSQL.Query -> [q] -> PostgreSQL m [r]
+
+makeEffect ''PostgreSQL
+
+-- | British alias of 'withTransactionSerializable'.
+withTransactionSerialisable ::
+  (HasCallStack, PostgreSQL :> es) => Eff es a -> Eff es a
+withTransactionSerialisable = withTransactionSerializable
+{-# INLINE withTransactionSerialisable #-}
+
+localUnliftWithConn ::
+  (HasCallStack, WithConnection :> es, IOE :> es) =>
+  LocalEnv localEs es ->
+  (PSQL.Connection -> (forall b. Eff localEs b -> IO b) -> IO a) ->
+  Eff es a
+localUnliftWithConn env f =
+  withConnection $ \conn ->
+    localSeqUnliftIO env $ \unlift ->
+      liftIO $ f conn unlift
+{-# INLINE localUnliftWithConn #-}
+
+(...) :: (a -> b) -> (t1 -> t2 -> a) -> t1 -> t2 -> b
+unlift ... f = \a' row -> unlift $ f a' row
+
+{- | Obvious interepreter for 'PostgreSQL'. Just gets a 'PSQL.Connection' from 'WithConnection' and calls the
+corresponding function from "Database.PostgreSQL.Simple".
+-}
+runPostgreSQL :: forall es a. (HasCallStack, WithConnection :> es, IOE :> es) => Eff (PostgreSQL : es) a -> Eff es a
+runPostgreSQL = interpret $ \env -> \case
+  Query q row ->
+    withConnection $ \conn -> liftIO (PSQL.query conn q row)
+  QueryWith parser q row ->
+    withConnection $ \conn -> liftIO (PSQL.queryWith parser conn q row)
+  Query_ row ->
+    withConnection $ \conn -> liftIO (PSQL.query_ conn row)
+  QueryWith_ parser row ->
+    withConnection $ \conn -> liftIO (PSQL.queryWith_ parser conn row)
+  Execute q row -> withConnection $ \conn -> liftIO (PSQL.execute conn q row)
+  Execute_ q -> withConnection $ \conn -> liftIO (PSQL.execute_ conn q)
+  ExecuteMany q row -> withConnection $ \conn -> liftIO (PSQL.executeMany conn q row)
+  WithTransaction f -> localUnliftWithConn env $ \conn unlift -> PSQL.withTransaction conn (unlift f)
+  WithTransactionLevel level f -> localUnliftWithConn env $ \conn unlift -> PSQL.withTransactionLevel level conn (unlift f)
+  WithTransactionMode mode f -> localUnliftWithConn env $ \conn unlift -> PSQL.withTransactionMode mode conn (unlift f)
+  WithTransactionModeRetry mode shouldRetry f -> localUnliftWithConn env $ \conn unlift -> PSQL.withTransactionModeRetry mode shouldRetry conn (unlift f)
+  WithTransactionModeRetry' mode shouldRetry f -> localUnliftWithConn env $ \conn unlift -> PSQL.withTransactionModeRetry' mode shouldRetry conn (unlift f)
+  WithTransactionSerializable f -> localUnliftWithConn env $ \conn unlift -> PSQL.withTransactionSerializable conn (unlift f)
+  WithSavepoint f -> localUnliftWithConn env $ \conn unlift -> PSQL.withSavepoint conn (unlift f)
+  Begin -> withConnection $ liftIO . PSQL.begin
+  Commit -> withConnection $ liftIO . PSQL.commit
+  Rollback -> withConnection $ liftIO . PSQL.rollback
+  Fold q params a f ->
+    localUnliftWithConn env $ \conn unlift ->
+      PSQL.fold conn q params a (unlift ... f)
+  Fold_ q a f ->
+    localUnliftWithConn env $ \conn unlift ->
+      PSQL.fold_ conn q a (unlift ... f)
+  FoldWithOptions opts q params a f ->
+    localUnliftWithConn env $ \conn unlift ->
+      PSQL.foldWithOptions opts conn q params a (unlift ... f)
+  FoldWithOptions_ opts q a f ->
+    localUnliftWithConn env $ \conn unlift ->
+      PSQL.foldWithOptions_ opts conn q a (unlift ... f)
+  ForEach q row forR ->
+    localUnliftWithConn env $ \conn unlift ->
+      PSQL.forEach conn q row (unlift . forR)
+  ForEach_ q forR ->
+    localUnliftWithConn env $ \conn unlift ->
+      PSQL.forEach_ conn q (unlift . forR)
+  Returning q rows -> withConnection $ \conn -> liftIO $ PSQL.returning conn q rows
+  FoldWith parser q params a f ->
+    localUnliftWithConn env $ \conn unlift ->
+      PSQL.foldWith parser conn q params a (unlift ... f)
+  FoldWithOptionsAndParser opts parser q params a f ->
+    localUnliftWithConn env $ \conn unlift ->
+      PSQL.foldWithOptionsAndParser opts parser conn q params a (unlift ... f)
+  FoldWith_ parser q a f ->
+    localUnliftWithConn env $ \conn unlift ->
+      PSQL.foldWith_ parser conn q a (unlift ... f)
+  FoldWithOptionsAndParser_ opts parser q a f ->
+    localUnliftWithConn env $ \conn unlift ->
+      PSQL.foldWithOptionsAndParser_ opts parser conn q a (unlift ... f)
+  ForEachWith parser q row forR ->
+    localUnliftWithConn env $ \conn unlift ->
+      PSQL.forEachWith parser conn q row (unlift . forR)
+  ForEachWith_ parser q forR ->
+    localUnliftWithConn env $ \conn unlift ->
+      PSQL.forEachWith_ parser conn q (unlift . forR)
+  ReturningWith parser q rows -> withConnection $ \conn -> liftIO $ PSQL.returningWith parser conn q rows
+
+#if OTEL
+{- | An interpreter for the 'PostgreSQL' effect that runs database operations using OpenTelemetry instrumentation.
+
+Basically the same as 'runPostgreSQL' except it uses the functions from
+[OpenTelemetry.Instrumentation.PostgresqlSimple](https://hackage-content.haskell.org/package/hs-opentelemetry-instrumentation-postgresql-simple/docs/OpenTelemetry-Instrumentation-PostgresqlSimple.html).
+
+Note that the @enable-opentel@ cabal flag must be set to enable this functionality.
+-}
+runPostgreSQLOT :: forall es a. (HasCallStack, WithConnection :> es, IOE :> es) => Eff (PostgreSQL : es) a -> Eff es a
+runPostgreSQLOT = interpret $ \env -> \case
+  Query q row ->
+    withConnection $ \conn -> OT.query conn q row
+  QueryWith parser q row ->
+    withConnection $ \conn -> OT.queryWith parser conn q row
+  Query_ row ->
+    withConnection $ \conn -> OT.query_ conn row
+  QueryWith_ parser row ->
+    withConnection $ \conn -> OT.queryWith_ parser conn row
+  Execute q row -> withConnection $ \conn -> OT.execute conn q row
+  Execute_ q -> withConnection $ \conn -> OT.execute_ conn q
+  ExecuteMany q row -> withConnection $ \conn -> OT.executeMany conn q row
+  WithTransaction f -> localUnliftWithConn env $ \conn unlift -> OT.withTransaction conn (unlift f)
+  WithTransactionLevel level f -> localUnliftWithConn env $ \conn unlift -> PSQL.withTransactionLevel level conn (unlift f)
+  WithTransactionMode mode f -> localUnliftWithConn env $ \conn unlift -> PSQL.withTransactionMode mode conn (unlift f)
+  WithTransactionModeRetry mode shouldRetry f -> localUnliftWithConn env $ \conn unlift -> PSQL.withTransactionModeRetry mode shouldRetry conn (unlift f)
+  WithTransactionModeRetry' mode shouldRetry f -> localUnliftWithConn env $ \conn unlift -> PSQL.withTransactionModeRetry' mode shouldRetry conn (unlift f)
+  WithTransactionSerializable f -> localUnliftWithConn env $ \conn unlift -> PSQL.withTransactionSerializable conn (unlift f)
+  WithSavepoint f -> localUnliftWithConn env $ \conn unlift -> OT.withSavepoint conn (unlift f)
+  Begin -> withConnection $ liftIO . OT.begin
+  Commit -> withConnection $ liftIO . OT.commit
+  Rollback -> withConnection $ liftIO . OT.rollback
+  Fold q params a f ->
+    localUnliftWithConn env $ \conn unlift ->
+      OT.fold conn q params a (unlift ... f)
+  Fold_ q a f ->
+    localUnliftWithConn env $ \conn unlift ->
+      OT.fold_ conn q a (unlift ... f)
+  FoldWithOptions opts q params a f ->
+    localUnliftWithConn env $ \conn unlift ->
+      OT.foldWithOptions opts conn q params a (unlift ... f)
+  FoldWithOptions_ opts q a f ->
+    localUnliftWithConn env $ \conn unlift ->
+      OT.foldWithOptions_ opts conn q a (unlift ... f)
+  ForEach q row forR ->
+    localUnliftWithConn env $ \conn unlift ->
+      OT.forEachWith PSQL.fromRow conn q row (unlift . forR)
+  ForEach_ q forR ->
+    localUnliftWithConn env $ \conn unlift ->
+      OT.forEach_ conn q (unlift . forR)
+  Returning q rows -> withConnection $ \conn -> OT.returning conn q rows
+  FoldWith parser q params a f ->
+    localUnliftWithConn env $ \conn unlift ->
+      OT.foldWith parser conn q params a (unlift ... f)
+  FoldWithOptionsAndParser opts parser q params a f ->
+    localUnliftWithConn env $ \conn unlift ->
+      OT.foldWithOptionsAndParser opts parser conn q params a (unlift ... f)
+  FoldWith_ parser q a f ->
+    localUnliftWithConn env $ \conn unlift ->
+      OT.foldWith_ parser conn q a (unlift ... f)
+  FoldWithOptionsAndParser_ opts parser q a f ->
+    localUnliftWithConn env $ \conn unlift ->
+      OT.foldWithOptionsAndParser_ opts parser conn q a (unlift ... f)
+  ForEachWith parser q row forR ->
+    localUnliftWithConn env $ \conn unlift ->
+      OT.forEachWith parser conn q row (unlift . forR)
+  ForEachWith_ parser q forR ->
+    localUnliftWithConn env $ \conn unlift ->
+      OT.forEachWith_ parser conn q (unlift . forR)
+  ReturningWith parser q rows -> withConnection $ \conn -> OT.returningWith parser conn q rows
+#endif
