diff --git a/hasql-backend.cabal b/hasql-backend.cabal
--- a/hasql-backend.cabal
+++ b/hasql-backend.cabal
@@ -1,7 +1,7 @@
 name:
   hasql-backend
 version:
-  0.2.2
+  0.3.0
 synopsis:
   API for backends of "hasql"
 description:
@@ -50,7 +50,10 @@
     text < 1.3,
     vector < 0.11,
     -- control:
+    either >= 4.3 && < 4.4,
+    free >= 4.6 && < 5,
     list-t < 0.5,
+    transformers >= 0.3 && < 0.5,
     -- general:
     base-prelude < 0.2,
     base >= 4.5 && < 4.8
diff --git a/library/Hasql/Backend.hs b/library/Hasql/Backend.hs
--- a/library/Hasql/Backend.hs
+++ b/library/Hasql/Backend.hs
@@ -5,119 +5,136 @@
 import Hasql.Backend.Prelude
 
 
-data Error =
-  -- |
-  -- Cannot connect to a server.
-  CantConnect Text |
-  -- |
-  -- The connection got interrupted.
-  ConnectionLost Text |
-  -- |
-  -- Some kind of error on backend.
-  ErroneousResult Text |
-  -- |
-  -- An unexpected or an unparsable result.
-  UnexpectedResult Text |
-  -- |
-  -- An unparsable statement template.
-  UnparsableTemplate Text |
+-- * Connection
+-------------------------
+
+class Cx c where
   -- |
-  -- A transaction concurrency conflict, 
-  -- which indicates that it should be retried.
-  TransactionConflict |
+  -- Connection settings.
+  type CxSettings c
   -- |
-  -- An operation, 
-  -- which requires a database transaction was executed without one.
-  NotInTransaction
-  deriving (Show, Typeable)
+  -- A connection acquisition error.
+  type CxError c
+  acquireCx :: CxSettings c -> IO (Either (CxError c) c)
+  releaseCx :: c -> IO ()
 
-instance Exception Error
 
+-- * Results
+-------------------------
 
+-- | A raw value returned from the database.
+data family ResultValue c
+
+-- | A raw result row.
+type ResultRow c =
+  Vector (ResultValue c)
+
 -- |
+-- A stream of rows of a result.
+type ResultStream c =
+  ListT IO (ResultRow c)
+
+-- |
+-- A matrix of a result.
+type ResultMatrix c =
+  Vector (ResultRow c)
+
+
+-- * Statements
+-------------------------
+
+-- | 
+-- A statement template packed with its values and settings.
+data Stmt c =
+  Stmt {
+    stmtTemplate :: !Text,
+    stmtParams :: !(Vector (StmtParam c)),
+    stmtPreparable :: !Bool
+  }
+
+-- | A prepared statement parameter.
+data family StmtParam c
+
+
+-- * Mapping
+-------------------------
+
+-- |
+-- A support by a backend of mapping a specific data type.
+class CxValue c v where
+  encodeValue :: v -> StmtParam c
+  decodeValue :: ResultValue c -> Either Text v
+
+
+-- * Transaction
+-------------------------
+
+-- | A transaction execution support.
+class CxTx c where
+  -- | A transaction error.
+  type TxError c
+  -- | 
+  -- Given an established connection execute a transaction,
+  -- returning either an error or a maybe result,
+  -- in which a 'Nothing' indicates that the transaction should be retried.
+  runTx :: c -> TxMode -> Tx c a -> IO (Either (TxError c) (Maybe a))
+
+-- |
 -- For reference see
 -- <https://en.wikipedia.org/wiki/Isolation_(database_systems)#Isolation_levels the Wikipedia info>.
-data IsolationLevel =
-  Serializable |
+data TxIsolationLevel =
   RepeatableReads |
+  Serializable |
   ReadCommitted |
   ReadUncommitted
 
-
 -- |
--- An isolation level and a boolean, 
--- defining, whether the transaction will perform the "write" operations.
-type TransactionMode =
-  (IsolationLevel, Bool)
-
+-- A mode, defining how a transaction should be executed.
+-- 
+-- * @Just (isolationLevel, write)@ indicates that a database transaction
+-- should be established with a specified isolation level and a write mode.
+-- 
+-- * @Nothing@ indicates that there should be no database transaction established on
+-- the backend and therefore it should be executed with no ACID guarantees,
+-- but also without any induced overhead.
+type TxMode =
+  Maybe (TxIsolationLevel, TxWriteMode)
 
 -- |
--- A stream of rows of a result.
-type Stream b =
-  ListT IO (Vector (Result b))
+-- * @Nothing@ indicates a \"read\" mode.
+-- 
+-- * @Just True@ indicates a \"write\" mode.
+-- 
+-- * @Just False@ indicates a \"write\" mode without committing.
+-- This is useful for testing, 
+-- allowing you to modify your database, 
+-- producing some result based on your changes,
+-- and to let Hasql roll all the changes back on the exit from the transaction.
+type TxWriteMode =
+  Maybe Bool
 
--- |
--- A matrix of a result.
-type Matrix b =
-  Vector (Vector (Result b))
+type Tx c = 
+  FreeT (TxF c) (MaybeT (EitherT (TxError c) IO))
 
+data TxF c x =
+  UnitTx (Stmt c) x |
+  CountTx (Stmt c) (Word64 -> x) |
+  VectorTx (Stmt c) (Vector (ResultRow c) -> x) |
+  StreamTx (Stmt c) (ListT (Tx c) (ResultRow c) -> x)
+  deriving (Functor)
 
--- |
--- A statement template with values for placeholders
--- and a flag, defining, whether it is preparable.
-type Statement b =
-  (ByteString, [StatementArgument b], Bool)
 
+unitTx :: Stmt c -> Tx c ()
+unitTx s = liftF (UnitTx s ())
 
-class Backend b where
-  -- |
-  -- An argument prepared for a statement.
-  data StatementArgument b
-  -- |
-  -- A raw value returned from the database.
-  data Result b
-  -- |
-  -- A backend-specific connection.
-  data Connection b
-  -- |
-  -- Open a connection using the backend's settings.
-  connect :: b -> IO (Connection b)
-  -- |
-  -- Close the connection.
-  disconnect :: Connection b -> IO ()
-  -- |
-  -- Execute a statement.
-  execute :: Statement b -> Connection b -> IO ()
-  -- |
-  -- Execute a statement
-  -- and get a matrix of results.
-  executeAndGetMatrix :: Statement b -> Connection b -> IO (Matrix b)
-  -- |
-  -- Execute a statement
-  -- and stream the results using a cursor.
-  -- This function will only be used from inside of transactions.
-  executeAndStream :: Statement b -> Connection b -> IO (Stream b)
-  -- |
-  -- Execute a statement,
-  -- returning the amount of affected rows.
-  executeAndCountEffects :: Statement b -> Connection b -> IO Word64
-  -- |
-  -- Start a transaction in the specified mode.
-  beginTransaction :: TransactionMode -> Connection b -> IO ()
-  -- |
-  -- Finish the transaction, 
-  -- while releasing all the resources acquired with 'executeAndStream'.
-  --  
-  -- The boolean defines whether to commit the updates,
-  -- otherwise it rolls back.
-  finishTransaction :: Bool -> Connection b -> IO ()
+countTx :: Stmt c -> Tx c Word64
+countTx s = liftF (CountTx s id)
 
+vectorTx :: Stmt c -> Tx c (Vector (ResultRow c))
+vectorTx s = liftF (VectorTx s id)
 
--- |
--- Support by a backend of a specific data type.
-class Mapping b v where
-  renderValue :: v -> StatementArgument b
-  parseResult :: Result b -> Either Text v
+streamTx :: Stmt c -> Tx c (ListT (Tx c) (ResultRow c))
+streamTx s = liftF (StreamTx s id)
 
 
 
diff --git a/library/Hasql/Backend/Prelude.hs b/library/Hasql/Backend/Prelude.hs
--- a/library/Hasql/Backend/Prelude.hs
+++ b/library/Hasql/Backend/Prelude.hs
@@ -7,11 +7,27 @@
 
 -- base-prelude
 -------------------------
-import BasePrelude as Exports
+import BasePrelude as Exports hiding (left, right, isLeft, isRight)
 
+-- transformers
+-------------------------
+import Control.Monad.IO.Class as Exports
+import Control.Monad.Trans.Class as Exports
+import Control.Monad.Trans.Maybe as Exports
+
 -- list-t
 -------------------------
 import ListT as Exports (ListT)
+
+-- either
+-------------------------
+import Control.Monad.Trans.Either as Exports
+import Data.Either.Combinators as Exports
+
+-- free
+-------------------------
+import Control.Monad.Trans.Free as Exports
+import Control.Monad.Free.TH as Exports
 
 -- text
 -------------------------
