diff --git a/hasql.cabal b/hasql.cabal
--- a/hasql.cabal
+++ b/hasql.cabal
@@ -1,7 +1,7 @@
 name:
   hasql
 version:
-  0.2.3
+  0.3.0
 synopsis:
   A minimalistic general high level API for relational databases
 description:
@@ -105,7 +105,7 @@
     bytestring == 0.10.*,
     text >= 1.0 && < 1.3,
     -- control:
-    list-t >= 0.2.4 && < 0.3,
+    list-t >= 0.2.4 && < 0.4,
     monad-control == 0.3.*,
     transformers-base == 0.4.*,
     -- errors:
@@ -137,10 +137,10 @@
   default-language:
     Haskell2010
   build-depends:
-    HTF == 0.12.*,
-    hasql == 0.2.*,
+    hasql,
     hasql-backend == 0.2.*,
     base-prelude == 0.1.*,
+    HTF == 0.12.*,
     base >= 4.5 && < 4.8
 
 
@@ -160,13 +160,13 @@
   default-language:
     Haskell2010
   build-depends:
-    HTF == 0.12.*,
+    hasql,
     hasql-postgres == 0.7.*,
-    hasql == 0.2.*,
     scientific == 0.3.*,
     transformers >= 0.2 && < 0.5,
     mtl-prelude < 3,
     base-prelude == 0.1.*,
+    HTF == 0.12.*,
     base >= 4.5 && < 4.8
 
 
@@ -188,8 +188,8 @@
   default-language:
     Haskell2010
   build-depends:
+    hasql,
     hasql-postgres == 0.7.*,
-    hasql == 0.2.*,
     transformers >= 0.2 && < 0.5,
     base >= 4.5 && < 4.8
 
diff --git a/library/Hasql.hs b/library/Hasql.hs
--- a/library/Hasql.hs
+++ b/library/Hasql.hs
@@ -8,6 +8,7 @@
   -- * Session
   Session,
   session,
+  sessionUnlifter,
 
   -- ** Session Settings
   SessionSettings,
@@ -62,34 +63,81 @@
 -- |
 -- A monad transformer,
 -- which executes transactions.
-type Session b =
-  ReaderT (Pool.Pool (Backend.Connection b))
+-- 
+-- * @b@ is a backend.
+-- 
+-- * @s@ is an anonymous variable, 
+-- used to associate 'sessionUnlifter' with a specific session. 
+-- 
+-- * @m@ is an inner (transformed) monad.
+-- 
+-- * @r@ is a result.
+newtype Session b s m r =
+  Session (ReaderT (Pool.Pool (Backend.Connection b)) m r)
+  deriving (Functor, Applicative, Monad, MonadTrans, MonadIO)
 
+instance MonadTransControl (Session b s) where
+  newtype StT (Session b s) a = SessionStT a
+  liftWith onRunner =
+    Session $ ReaderT $ \e -> onRunner $ \(Session (ReaderT f)) -> liftM SessionStT $ f e
+  restoreT = 
+    Session . ReaderT . const . liftM (\(SessionStT a) -> a)
+
+instance (MonadBase IO m) => MonadBase IO (Session b s m) where
+  liftBase = Session . liftBase
+
+instance (MonadBaseControl IO m) => MonadBaseControl IO (Session b s m) where
+  newtype StM (Session b s m) a = SessionStM (ComposeSt (Session b s) m a)
+  liftBaseWith = defaultLiftBaseWith SessionStM
+  restoreM = defaultRestoreM $ \(SessionStM x) -> x
+
+
 -- |
 -- Given backend settings, session settings, and a session monad transformer,
 -- execute it in the inner monad.
+-- 
+-- It uses the same trick as 'ST' with the anonymous @s@ type argument
+-- to prohibit the use of the result of
+-- 'sessionUnlifter' outside of its creator session.
 session :: 
   (Backend.Backend b, MonadBaseControl IO m) =>
-  b -> SessionSettings -> Session b m r -> m r
-session backend (SessionSettings size timeout) reader =
-  join $ liftM restoreM $ liftBaseWith $ \runInIO ->
+  b -> SessionSettings -> (forall s. Session b s m r) -> m r
+session backend (SessionSettings size timeout) s =
+  control $ \runInIO ->
     mask $ \unmask -> do
       p <- Pool.createPool (Backend.connect backend) Backend.disconnect 1 timeout size
-      r <- try $ unmask $ runInIO $ runReaderT reader p
+      r <- try $ unmask $ runInIO $ runSession p s
       Pool.purgePool p
-      either onException return r
-  where
-    onException =
-      \case
-        Backend.CantConnect t -> throwIO $ CantConnect t
-        Backend.ConnectionLost t -> throwIO $ ConnectionLost t
-        Backend.ErroneousResult t -> throwIO $ ErroneousResult t
-        Backend.UnexpectedResult t -> throwIO $ UnexpectedResult t
-        Backend.UnparsableTemplate t -> throwIO $ UnparsableTemplate t
-        Backend.TransactionConflict -> $bug "Unexpected TransactionConflict exception"
-        Backend.NotInTransaction -> throwIO $ NotInTransaction
+      either (throwIO :: SomeException -> IO r) return r
 
+-- |
+-- Get a session unlifting function, 
+-- which allows to execute a session in the inner monad
+-- using the resources of the current session.
+-- 
+-- Using this function in combination with 'lift'
+-- you can interleave 'Session' with other monad transformers.
+-- 
+-- This function has the following property:
+-- 
+-- > (sessionUnlifter >>= \unlift -> lift (unlift m)) ≡ m
+sessionUnlifter :: (MonadBaseControl IO m) => Session b s m (Session b s m r -> m r)
+sessionUnlifter =
+  Session $ ReaderT $ return . runSession
 
+runSession :: (MonadBaseControl IO m) => Pool.Pool (Backend.Connection b) -> Session b s m r -> m r
+runSession e (Session r) =
+  control $ \runInIO -> 
+    catch (runInIO (runReaderT r e)) $ \case
+      Backend.CantConnect t -> throwIO $ CantConnect t
+      Backend.ConnectionLost t -> throwIO $ ConnectionLost t
+      Backend.ErroneousResult t -> throwIO $ ErroneousResult t
+      Backend.UnexpectedResult t -> throwIO $ UnexpectedResult t
+      Backend.UnparsableTemplate t -> throwIO $ UnparsableTemplate t
+      Backend.TransactionConflict -> $bug "Unexpected TransactionConflict exception"
+      Backend.NotInTransaction -> throwIO $ NotInTransaction
+
+
 -- ** Session Settings
 -------------------------
 
@@ -160,8 +208,8 @@
 -------------------------
 
 -- |
--- A transaction specialized for backend @b@, 
--- running on an anonymous state-thread @s@ 
+-- A transaction specialized for a backend @b@, 
+-- associated with its intermediate results using an anonymous type-argument @s@ (same as in 'ST')
 -- and producing a result @r@.
 newtype Tx b s r =
   Tx (ReaderT (Backend.Connection b) IO r)
@@ -182,11 +230,14 @@
 
 -- |
 -- Execute a transaction in a session.
+-- 
+-- This function ensures on the type level, 
+-- that it's impossible to return @'TxListT' s m r@ from it.
 tx :: 
   (Backend.Backend b, MonadBase IO m) =>
-  Mode -> (forall s. Tx b s r) -> Session b m r
+  Mode -> (forall s. Tx b s r) -> Session b s m r
 tx m t =
-  ReaderT $ \p -> liftBase $ Pool.withResource p $ \c -> runTx c m t
+  Session $ ReaderT $ \p -> liftBase $ Pool.withResource p $ \c -> runTx c m t
   where
     runTx ::
       Backend b => 
diff --git a/postgres-tests/Main.hs b/postgres-tests/Main.hs
--- a/postgres-tests/Main.hs
+++ b/postgres-tests/Main.hs
@@ -26,7 +26,7 @@
     return ()
 
 
-session :: H.Session HP.Postgres IO r -> IO r
+session :: (forall s. H.Session HP.Postgres s IO r) -> IO r
 session =
   H.session backendSettings poolSettings
   where
