diff --git a/couchdb-conduit.cabal b/couchdb-conduit.cabal
--- a/couchdb-conduit.cabal
+++ b/couchdb-conduit.cabal
@@ -1,8 +1,8 @@
 name:           couchdb-conduit
-version:        0.4.2
+version:        0.5.0
 cabal-version:  >= 1.8
 build-type:     Simple
-stability:      Experimental
+stability:      Stable
 category:       Database, Conduit
 license:        BSD3
 license-file:   LICENSE
@@ -45,18 +45,20 @@
                    data-default,
                    blaze-builder >= 0.2.1 && < 0.4
   ghc-options:      -Wall
-  exposed-modules:  
-                    Database.CouchDB.Conduit,
-                    Database.CouchDB.Conduit.DB,
-                    Database.CouchDB.Conduit.Design,
-                    Database.CouchDB.Conduit.Explicit,
-                    Database.CouchDB.Conduit.Generic,
-                    Database.CouchDB.Conduit.LowLevel,
-                    Database.CouchDB.Conduit.View
-  other-modules:    
-                    Database.CouchDB.Conduit.Internal.Doc,
-                    Database.CouchDB.Conduit.Internal.Parser,
-                    Database.CouchDB.Conduit.Internal.View
+  exposed-modules:  
+                    Database.CouchDB.Conduit,
+                    Database.CouchDB.Conduit.DB,
+                    Database.CouchDB.Conduit.Design,
+                    Database.CouchDB.Conduit.Explicit,
+                    Database.CouchDB.Conduit.Generic,
+                    Database.CouchDB.Conduit.LowLevel,
+                    Database.CouchDB.Conduit.View
+  other-modules:    
+                    Database.CouchDB.Conduit.Internal.Doc,
+                    Database.CouchDB.Conduit.Internal.Parser,
+                    Database.CouchDB.Conduit.Internal.View,
+                    Database.CouchDB.Conduit.Internal.Connection,
+                    Database.CouchDB.Conduit.Implicit
 
 test-suite test
   type:            exitcode-stdio-1.0
@@ -64,9 +66,7 @@
   build-depends:   
                    base >= 4,
                    HUnit >= 1.2 && < 2,
-                   QuickCheck >= 2.4,
                    test-framework >= 0.4.1,
-                   test-framework-quickcheck2,
                    test-framework-hunit,
                    couchdb-conduit,
                    aeson >= 0.6 && < 0.7,
diff --git a/src/Database/CouchDB/Conduit.hs b/src/Database/CouchDB/Conduit.hs
--- a/src/Database/CouchDB/Conduit.hs
+++ b/src/Database/CouchDB/Conduit.hs
@@ -1,20 +1,12 @@
-{-# LANGUAGE DeriveDataTypeable #-}
-{-# LANGUAGE OverloadedStrings #-}
-{-# LANGUAGE FlexibleInstances #-}
-{-# LANGUAGE FlexibleContexts #-}
+{- | CouchDB 
 
-{- | 
 To work with concrete objects, use the following modules:
   
-  * "Database.CouchDB.Conduit.DB"
-  
-  * "Database.CouchDB.Conduit.View"
-  
-  * "Database.CouchDB.Conduit.Explicit"
+  * "Database.CouchDB.Conduit.DB" Database
   
-  * "Database.CouchDB.Conduit.Generic"
+  * "Database.CouchDB.Conduit.View" Views
   
-  * "Database.CouchDB.Conduit.LowLevel"
+  * "Database.CouchDB.Conduit.LowLevel" Low-level methods
    
 For complete documentation about The Couch DB HTTP API see
 <http://wiki.apache.org/couchdb/Complete_HTTP_API_Reference>
@@ -22,9 +14,7 @@
 
 module Database.CouchDB.Conduit (
     -- * Document paths and revisions #path#
-    -- $path
     Path,
-    mkPath,
     Revision,
     
     -- * CouchDB Connection #connection#
@@ -33,157 +23,52 @@
     couchHost,
     couchPort,
     couchManager,
-    couchDB,
     couchLogin,
     couchPass,
     
     -- * Runtime enviroment and errors #runtime#
-    -- $runtime
     MonadCouch (..),
     CouchError (..),
     runCouch,
     withCouchConnection,
     
+    -- * Documents
+    --   
+    --   For accessing and storing document data, use one of following: 
+    --
+    --   * "Database.CouchDB.Conduit.Explicit" Explicit JSON methods
+    --   
+    --   * "Database.CouchDB.Conduit.Generic" Generic JSON methods
+    couchRev, 
+    couchRev',
+    couchDelete
+    
 ) where
 
-import              Control.Monad.Trans.Reader (ReaderT, ask, runReaderT)
-import              Control.Exception (Exception)
-import              Control.Monad.Trans.Class (lift)
-
-import              Data.Conduit (ResourceIO, ResourceT, runResourceT)
-
-import qualified    Network.HTTP.Conduit as H
-import qualified    Network.HTTP.Types as HT
-
-import              Data.Generics (Typeable)
-import              Data.Default (Default (def))
-import qualified    Data.ByteString as B
-import qualified    Data.Text.Encoding as TE
-import qualified    Blaze.ByteString.Builder as BLB
-
------------------------------------------------------------------------------
--- Paths
------------------------------------------------------------------------------
-
--- $path 
--- As a rule, full path to document in CouchDB is just URL path. But there is 
--- one subtlety. For example, document ids /can/ contain slashes. But, 
--- to work with such objects, path fragments must be escaped.
--- 
--- > database/doc%2Fname
---
--- But, fo non-document items such as views, attachments e.t.c., slashes
--- between path fragments /must not/ be escaped. While slashes in path 
--- fragments /must/ be escaped.
--- 
--- > database/_design/my%2Fdesign/_view/my%2Fview
-
--- | Represents a path or path fragment.
-type Path = B.ByteString
-
--- | Represents a revision of a CouchDB Document. 
-type Revision = B.ByteString
-
--- | Make correct path from escaped fragments. Filter empty fragments.
---
--- > mkPath ["db", "", "doc/with/slashes"]
--- > db/doc%2Fwith%2Fslashes
-mkPath :: [Path]    -- ^ Path fragments be escaped.  
-       -> Path
-mkPath = BLB.toByteString . HT.encodePathSegments . 
-    map TE.decodeUtf8 . filter (/="")
-
------------------------------------------------------------------------------
--- Connection
------------------------------------------------------------------------------
-
--- | Represents a single connection to CouchDB server. The constructor for this 
---   data type is not exposed. Instead, you should use either the 'def' method 
---   to retrieve a default instance.
-data CouchConnection = CouchConnection {
-      couchHost :: B.ByteString     
-        -- ^ Hostname. Default value is \"localhost\"
-    , couchPort :: Int              
-        -- ^ Port. 5984 by default.
-    , couchManager :: Maybe H.Manager  
-        -- ^ Connection 'Manager'. 'Nothing' by default. If you need to use
-        --   your 'H.Manager' (for connection pooling for example), set it to
-        --   'Just' 'H.Manager'.
-    , couchDB :: Path             
-        -- ^ Database name. This value is prepended to 'Path' to form the full 
-        --   path in all requests.
-        --    
-        --   By default is 'B.empty'. This makes it possible to access 
-        --   different databases through a single connection. But, in this 
-        --   case, all requests must be preceded by the database name with 
-        --   unescaped slash. See 'Path' for details.
-    , couchLogin :: B.ByteString
-        -- ^ CouchDB login. By default is 'B.empty'.
-    , couchPass :: B.ByteString
-        -- ^ CouchDB password. By default is 'B.empty'.
-}
-
-instance Default CouchConnection where
-    def = CouchConnection "localhost" 5984 Nothing B.empty B.empty B.empty
-
------------------------------------------------------------------------------
--- Runtime
------------------------------------------------------------------------------
-
--- $runtime
--- All functions to access CouchDB require a 'MonadCouch' instance to 
--- access the connection information.  'ReaderT' is an instance of 
--- 'MonadCouch', and /runCouch/ runs a sequence of database actions using 
--- 'ReaderT' and 'ResourceT'.
--- 
--- If your db code is part of a larger monad, it makes sense to just make the 
--- larger monad an instance of 'MonadCouch' and skip the intermediate ReaderT, 
--- since then performance is improved by eliminating one monad from the final 
--- transformer stack.
-
--- | A monad which allows access to the connection.
-class ResourceIO m => MonadCouch m where
-    couchConnection :: m CouchConnection
-
-instance (ResourceIO m) => MonadCouch (ReaderT CouchConnection m) where
-    couchConnection = ask
+import Data.Conduit (ResourceT)
+import Database.CouchDB.Conduit.Internal.Connection
+import qualified Database.CouchDB.Conduit.Internal.Doc as D
 
--- | A CouchDB Error.
-data CouchError 
-    = CouchHttpError Int B.ByteString
-        -- ^ Error comes from http.
-    | CouchInternalError B.ByteString
-        -- ^ Non-http errors include things like errors  
-        --   parsing the response.
-    | NotModified
-        -- ^ /Is not an error actually/. It is thrown when CouchDB returns 
-        --   @304 - Not Modified@ response to the request. See 
-        --   <http://wiki.apache.org/couchdb/HTTP_Document_API>
-  deriving (Show, Typeable)
-instance Exception CouchError
+-- | Get Revision of a document.
+couchRev :: MonadCouch m => 
+       Path       -- ^ Database.
+    -> Path       -- ^ Document path.
+    -> ResourceT m Revision
+couchRev db p = D.couchRev (mkPath [db, p]) 
 
--- | Run a sequence of CouchDB actions. This function is a combination of 
---   'withCouchConnection', 'runReaderT' and 'runResourceT'.
---  
---   If you create your own instance of 'MonadCouch', use 'withCouchConnection'.  
-runCouch :: ResourceIO m =>
-       CouchConnection                            -- ^ Couch connection
-    -> ResourceT (ReaderT CouchConnection m) a    -- ^ CouchDB actions
-    -> m a
-runCouch c = withCouchConnection c . runReaderT . runResourceT
+-- | Brain-free version of 'couchRev'. If document absent, 
+--   just return 'B.empty'.
+couchRev' :: MonadCouch m => 
+       Path       -- ^ Database.
+    -> Path       -- ^ Document path.
+    -> ResourceT m Revision
+couchRev' db p = D.couchRev' (mkPath [db, p]) 
 
--- | Connect to a CouchDB server, call the supplied function, and then close 
---   the connection.
--- 
--- > withCouchConnection def {couchDB = "db"} . runReaderT . runResourceT $ do
--- >    ... -- actions
-withCouchConnection :: ResourceIO m =>
-       CouchConnection              -- ^ Couch connection
-    -> (CouchConnection -> m a)     -- ^ Function to run
-    -> m a
-withCouchConnection c@(CouchConnection _ _ mayMan _ _ _) f = 
-    case mayMan of
-        -- Allocate manager with helper
-        Nothing -> H.withManager $ \m -> lift $ f $ c {couchManager = Just m}
-        _ -> f c
+-- | Delete the given revision of the object.  
+couchDelete :: MonadCouch m => 
+       Path       -- ^ Database.
+    -> Path       -- ^ Document path.
+    -> Revision             -- ^ Revision
+    -> ResourceT m ()
+couchDelete db p = D.couchDelete (mkPath [db, p]) 
 
diff --git a/src/Database/CouchDB/Conduit/DB.hs b/src/Database/CouchDB/Conduit/DB.hs
--- a/src/Database/CouchDB/Conduit/DB.hs
+++ b/src/Database/CouchDB/Conduit/DB.hs
@@ -18,6 +18,8 @@
     couchReplicateDB
 ) where
 
+import Control.Monad (void)
+
 import qualified Data.ByteString as B
 import qualified Data.Aeson as A
 
@@ -26,41 +28,50 @@
 import qualified Network.HTTP.Conduit as H
 import qualified Network.HTTP.Types as HT
 
-import Database.CouchDB.Conduit (MonadCouch(..))
+import Database.CouchDB.Conduit.Internal.Connection 
+            (MonadCouch(..), Path, mkPath)
 import Database.CouchDB.Conduit.LowLevel (couch, protect, protect')
 
 
 -- | Create CouchDB database. 
-couchPutDB :: MonadCouch m => ResourceT m ()
-couchPutDB = couch HT.methodPut id [] []
-                    (H.RequestBodyBS B.empty) protect' 
-                    >> return ()
+couchPutDB :: MonadCouch m => 
+       Path             -- ^ Database
+    -> ResourceT m ()
+couchPutDB db = void $ couch HT.methodPut 
+                            (mkPath [db]) [] [] 
+                            (H.RequestBodyBS B.empty)
+                            protect'
 
 -- | \"Don't care\" version of couchPutDb. Create CouchDB database only in its 
 --   absence. For this it handles @412@ responses.
-couchPutDB_ :: MonadCouch m => ResourceT m ()
-couchPutDB_ = couch HT.methodPut id [] []
+couchPutDB_ :: MonadCouch m => 
+       Path             -- ^ Database
+    -> ResourceT m ()
+couchPutDB_ db = void $ couch HT.methodPut 
+                    (mkPath [db]) [] []
                     (H.RequestBodyBS B.empty) 
                     (protect [200, 201, 202, 304, 412] return) 
-                    >> return ()
 
 -- | Delete a database.
-couchDeleteDB :: MonadCouch m => ResourceT m ()
-couchDeleteDB = couch HT.methodDelete id [] []
+couchDeleteDB :: MonadCouch m => 
+       Path             -- ^ Database
+    -> ResourceT m ()
+couchDeleteDB db = void $ couch HT.methodDelete 
+                    (mkPath [db]) [] []
                     (H.RequestBodyBS B.empty) protect' 
-                    >> return ()
 
 -- | Maintain DB security.
 couchSecureDB :: MonadCouch m => 
-       [B.ByteString]   -- ^ Admin roles 
+       Path             -- ^ Database
+    -> [B.ByteString]   -- ^ Admin roles 
     -> [B.ByteString]   -- ^ Admin names
     -> [B.ByteString]   -- ^ Readers roles 
     -> [B.ByteString]   -- ^ Readers names
     -> ResourceT m ()       
-couchSecureDB adminRoles adminNames readersRoles readersNames = 
-    couch HT.methodPut (`B.append` "/_security") [] []
+couchSecureDB db adminRoles adminNames readersRoles readersNames = 
+    void $ couch HT.methodPut 
+            (mkPath [db, "_security"]) [] []
             reqBody protect' 
-            >> return ()
   where
     reqBody = H.RequestBodyLBS $ A.encode $ A.object [
             "admins" A..= A.object [ "roles" A..= adminRoles,
@@ -80,9 +91,8 @@
     -> Bool             -- ^ Cancel flag
     -> ResourceT m ()
 couchReplicateDB source target createTarget continuous cancel = 
-    couch HT.methodPost (const "_replicate") [] []
+    void $ couch HT.methodPost "_replicate" [] []
             reqBody protect' 
-            >> return ()
   where
     reqBody = H.RequestBodyLBS $ A.encode $ A.object [
             "source" A..= source,
diff --git a/src/Database/CouchDB/Conduit/Design.hs b/src/Database/CouchDB/Conduit/Design.hs
--- a/src/Database/CouchDB/Conduit/Design.hs
+++ b/src/Database/CouchDB/Conduit/Design.hs
@@ -20,14 +20,16 @@
 import qualified    Data.Aeson as A
 import qualified    Data.Aeson.Types as AT
 
-import Database.CouchDB.Conduit (MonadCouch, CouchError, Path, mkPath, Revision)
+import Database.CouchDB.Conduit.Internal.Connection 
+        (MonadCouch, CouchError, Path, mkPath, Revision)
 import Database.CouchDB.Conduit.Internal.Doc (couchGetWith, 
             couchPutWith_, couchPutWith')
 
 -- | Put view in design document if it not exists. If design document does 
 --   not exist, it will be created. 
 couchPutView_ :: MonadCouch m =>
-       Path                 -- ^ Design document
+       Path                 -- ^ Database
+    -> Path                 -- ^ Design document
     -> Path                 -- ^ View name
     -> B.ByteString         -- ^ Map function
     -> Maybe B.ByteString   -- ^ Reduce function
@@ -37,7 +39,8 @@
 -- | Brute-force version of 'couchViewPut''. Put view in design document. 
 --   If design document does not exist, it will be created. 
 couchPutView' :: MonadCouch m =>
-       Path                 -- ^ Design document
+       Path                 -- ^ Database
+    -> Path                 -- ^ Design document
     -> Path                 -- ^ View name
     -> B.ByteString         -- ^ Map function
     -> Maybe B.ByteString   -- ^ Reduce function
@@ -49,19 +52,20 @@
 -----------------------------------------------------------------------------
 
 couchViewPutInt :: MonadCouch m =>
-       Bool
+       Bool                 -- ^ Care flag
+    -> Path                 -- ^ Database
     -> Path                 -- ^ Design document
     -> Path                 -- ^ View name
     -> B.ByteString         -- ^ Map function
     -> Maybe B.ByteString   -- ^ Reduce function
     -> ResourceT m Revision
-couchViewPutInt prot designName viewName mapF reduceF = do
+couchViewPutInt prot db designName viewName mapF reduceF = do
     -- Get design or empty object
     (_, A.Object d) <- getDesignDoc path
     if prot then couchPutWith_ A.encode path [] $ inferViews (purge_ d)
             else couchPutWith' A.encode path [] $ inferViews (purge_ d)
   where
-    path = designDocPath designName
+    path = designDocPath db designName
     inferViews d = A.Object $ M.insert "views" (addView d) d
     addView d = A.Object $ M.insert 
         (TE.decodeUtf8 viewName)
@@ -71,13 +75,15 @@
     constructView m (Just r) = A.object ["map" A..= m, "reduce" A..= r]
     constructView m Nothing = A.object ["map" A..= m]
 
-getDesignDoc :: MonadCouch m => Path -> ResourceT m (Revision, AT.Value)
+getDesignDoc :: MonadCouch m => 
+       Path 
+    -> ResourceT m (Revision, AT.Value)
 getDesignDoc designName = catch 
-        (couchGetWith A.Success (designDocPath designName) [])
+        (couchGetWith A.Success designName [])
         (\(_ :: CouchError) -> return (B.empty, AT.emptyObject))
     
-designDocPath :: Path -> Path
-designDocPath dn = mkPath ["_design", dn]
+designDocPath :: Path -> Path -> Path
+designDocPath db dn = mkPath [db, "_design", dn]
 
 -- | Purge underscore fields
 purge_ :: AT.Object -> AT.Object
diff --git a/src/Database/CouchDB/Conduit/Explicit.hs b/src/Database/CouchDB/Conduit/Explicit.hs
--- a/src/Database/CouchDB/Conduit/Explicit.hs
+++ b/src/Database/CouchDB/Conduit/Explicit.hs
@@ -21,21 +21,21 @@
 -- > instance ToJSON D where
 -- >    toJSON (D f1 f2) = object ["f1" .= f1, "f2" .= f2]
 -- > 
--- > runCouch def {couchDB="mydb"} $ do
+-- > runCouch def $ do
 -- >    -- Put new doc and update it
--- >    rev1 <- couchPut "my-doc1" "" [] $ D 123 "str"         
--- >    rev2 <- couchPut "my-doc1" rev1 [] $ D 1234 "another"
+-- >    rev1 <- couchPut "mydb" "my-doc1" "" [] $ D 123 "str"         
+-- >    rev2 <- couchPut "mydb" "my-doc1" rev1 [] $ D 1234 "another"
 -- >
 -- >    -- get it and print
--- >    (rev3, d1 :: D) <- couchGet "my-doc1" [] 
+-- >    (rev3, d1 :: D) <- couchGet "mydb" "my-doc1" [] 
 -- >    liftIO $ print d1
 -- >
 -- >    -- update it in brute-force manner    
--- >    couchPut' "my-doc1" [] $ D 12345 "third"    -- notice - no rev
+-- >    couchPut' "mydb" "my-doc1" [] $ D 12345 "third"    -- notice - no rev
 -- >    
 -- >    -- get revision and delete
--- >    rev3 <- couchRev "my-doc1"
--- >    couchDelete "my-doc1" rev3
+-- >    rev3 <- couchRev "mydb" "my-doc1"
+-- >    couchDelete "mydb" "my-doc1" rev3
 -- 
 --   For details of types see "Data.Aeson". To work with documents in 
 --   generic manner, look at "Database.CouchDB.Conduit.Generic".
@@ -43,25 +43,24 @@
 module Database.CouchDB.Conduit.Explicit (
     -- * Accessing documents
     couchGet,
-    couchRev,
-    couchRev',
     -- * Manipulating documents
     couchPut,
     couchPut_,
     couchPut',
-    couchDelete,
     -- * Working with views #view#
     toType
 ) where
 
-import qualified    Data.Aeson as A
-import              Data.Conduit (ResourceT, Conduit(..), ResourceIO)
+import qualified Data.Aeson as A
+import Data.Conduit (ResourceT, Conduit(..), ResourceIO)
 
-import              Network.HTTP.Types as HT
+import Network.HTTP.Types (Query)
 
-import              Database.CouchDB.Conduit (MonadCouch(..), Path, Revision)
-import              Database.CouchDB.Conduit.Internal.Doc 
-import              Database.CouchDB.Conduit.Internal.View (toTypeWith)
+import Database.CouchDB.Conduit.Internal.Connection (MonadCouch(..), 
+        Path, Revision, mkPath)
+import Database.CouchDB.Conduit.Internal.Doc (couchGetWith, couchPutWith, 
+        couchPutWith_, couchPutWith') 
+import Database.CouchDB.Conduit.Internal.View (toTypeWith)
 
 ------------------------------------------------------------------------------
 -- Document
@@ -69,38 +68,42 @@
 
 -- | Load a single 'A.ToJSON' object with 'Revision' from couch DB. 
 couchGet :: (MonadCouch m, A.FromJSON a) => 
-       Path         -- ^ Document path
-    -> HT.Query     -- ^ Query
+       Path         -- ^ Database
+    -> Path         -- ^ Document path
+    -> Query     -- ^ Query
     -> ResourceT m (Revision, a)
-couchGet = couchGetWith A.fromJSON
+couchGet db p = couchGetWith A.fromJSON (mkPath [db, p])
 
 -- | Put an 'A.FromJSON' object in Couch DB with revision, returning the 
 --   new 'Revision'.
 couchPut :: (MonadCouch m, A.ToJSON a) => 
-        Path        -- ^ Document path.
-     -> Revision    -- ^ Document revision. For new docs provide empty string.
-     -> HT.Query    -- ^ Query arguments.
-     -> a           -- ^ The object to store.
-     -> ResourceT m Revision      
-couchPut = couchPutWith A.encode
+       Path         -- ^ Database
+    -> Path         -- ^ Document path
+    -> Revision    -- ^ Document revision. For new docs provide empty string.
+    -> Query    -- ^ Query arguments.
+    -> a           -- ^ The object to store.
+    -> ResourceT m Revision      
+couchPut db p = couchPutWith A.encode (mkPath [db, p])
 
 -- | \"Don't care\" version of 'couchPut'. Creates document only in its 
 --   absence.
 couchPut_ :: (MonadCouch m, A.ToJSON a) => 
-        Path        -- ^ Document path.
-     -> HT.Query    -- ^ Query arguments.
-     -> a           -- ^ The object to store.
-     -> ResourceT m Revision      
-couchPut_ = couchPutWith_ A.encode
+       Path         -- ^ Database
+    -> Path         -- ^ Document path
+    -> Query    -- ^ Query arguments.
+    -> a           -- ^ The object to store.
+    -> ResourceT m Revision      
+couchPut_ db p = couchPutWith_ A.encode (mkPath [db, p])
 
 -- | Brute force version of 'couchPut'. Creates a document regardless of 
 --   presence. 
 couchPut' :: (MonadCouch m, A.ToJSON a) => 
-        Path        -- ^ Document path.
-     -> HT.Query    -- ^ Query arguments.
-     -> a           -- ^ The object to store.
-     -> ResourceT m Revision      
-couchPut' = couchPutWith' A.encode
+       Path         -- ^ Database
+    -> Path         -- ^ Document path
+    -> Query    -- ^ Query arguments.
+    -> a           -- ^ The object to store.
+    -> ResourceT m Revision      
+couchPut' db p = couchPutWith' A.encode (mkPath [db, p])
 
 ------------------------------------------------------------------------------
 -- View conduit
diff --git a/src/Database/CouchDB/Conduit/Generic.hs b/src/Database/CouchDB/Conduit/Generic.hs
--- a/src/Database/CouchDB/Conduit/Generic.hs
+++ b/src/Database/CouchDB/Conduit/Generic.hs
@@ -14,21 +14,21 @@
 -- > -- | Our doc with instances
 -- > data D = D { f1 :: Int, f2 :: String } deriving (Show, Data, Typeable)
 -- > 
--- > runCouch def {couchDB="mydb"} $ do
+-- > runCouch def $ do
 -- >    -- Put new doc and update it
--- >    rev1 <- couchPut "my-doc1" "" [] $ D 123 "str"         
--- >    rev2 <- couchPut "my-doc1" rev1 [] $ D 1234 "another"
+-- >    rev1 <- couchPut "mydb" "my-doc1" "" [] $ D 123 "str"         
+-- >    rev2 <- couchPut "mydb" "my-doc1" rev1 [] $ D 1234 "another"
 -- >
 -- >    -- get it and print
--- >    (rev3, d1 :: D) <- couchGet "my-doc1" [] 
+-- >    (rev3, d1 :: D) <- couchGet "mydb" "my-doc1" [] 
 -- >    liftIO $ print d1
 -- >
 -- >    -- update it in brute-force manner    
--- >    couchPut' "my-doc1" [] $ D 12345 "third"    -- notice - no rev
+-- >    couchPut' "mydb" "my-doc1" [] $ D 12345 "third"    -- notice - no rev
 -- >    
 -- >    -- get revision and delete
--- >    rev3 <- couchRev "my-doc1"
--- >    couchDelete "my-doc1" rev3
+-- >    rev3 <- couchRev "mydb" "my-doc1"
+-- >    couchDelete "mydb" "my-doc1" rev3
 --  
 --   The main advantage of this approach in the absence of tonns of  
 --   boilerplate code. The main disadvantage is inability to influence the 
@@ -40,61 +40,64 @@
 module Database.CouchDB.Conduit.Generic (
      -- * Accessing documents
     couchGet,
-    couchRev,
-    couchRev',
     -- * Manipulating documents
     couchPut,
     couchPut_,
     couchPut',
-    couchDelete,
     -- * Working with views #view#
     toType
 ) where
 
-import              Data.Generics (Data)
+import Data.Generics (Data)
 import qualified    Data.Aeson as A
 import qualified    Data.Aeson.Generic as AG
-import              Data.Conduit (ResourceT, Conduit(..), ResourceIO)
+import Data.Conduit (ResourceT, Conduit(..), ResourceIO)
 
-import qualified    Network.HTTP.Types as HT
+import Network.HTTP.Types (Query)
 
-import              Database.CouchDB.Conduit
-import              Database.CouchDB.Conduit.Internal.Doc
-import              Database.CouchDB.Conduit.Internal.View
+import Database.CouchDB.Conduit.Internal.Connection 
+            (MonadCouch(..), Path, mkPath, Revision)
+import Database.CouchDB.Conduit.Internal.Doc 
+            (couchGetWith, couchPutWith, couchPutWith_, couchPutWith')
+import Database.CouchDB.Conduit.Internal.View (toTypeWith)
 
 -- | Load a single object from couch DB.
 couchGet :: (MonadCouch m, Data a) => 
-       Path         -- ^ Document path
-    -> HT.Query     -- ^ Query
+       Path         -- ^ Database
+    -> Path         -- ^ Document path
+    -> Query     -- ^ Query
     -> ResourceT m (Revision, a)
-couchGet = couchGetWith AG.fromJSON  
+couchGet db p = couchGetWith AG.fromJSON (mkPath [db, p])  
 
 -- | Put an object in Couch DB with revision, returning the new Revision.
 couchPut :: (MonadCouch m, Data a) => 
-        Path        -- ^ Document path.
-     -> Revision    -- ^ Document revision. For new docs provide empty string.
-     -> HT.Query    -- ^ Query arguments.
-     -> a           -- ^ The object to store.
-     -> ResourceT m Revision      
-couchPut = couchPutWith AG.encode
+       Path         -- ^ Database
+    -> Path         -- ^ Document path
+    -> Revision     -- ^ Document revision. For new docs provide empty string.
+    -> Query        -- ^ Query arguments.
+    -> a            -- ^ The object to store.
+    -> ResourceT m Revision      
+couchPut db p = couchPutWith AG.encode (mkPath [db, p])
     
 -- | \"Don't care\" version of 'couchPut'. Creates document only in its 
 --   absence.
 couchPut_ :: (MonadCouch m, Data a) => 
-        Path        -- ^ Document path.
-     -> HT.Query    -- ^ Query arguments.
-     -> a           -- ^ The object to store.
-     -> ResourceT m Revision      
-couchPut_ = couchPutWith_ AG.encode
+       Path         -- ^ Database
+    -> Path         -- ^ Document path
+    -> Query    -- ^ Query arguments.
+    -> a           -- ^ The object to store.
+    -> ResourceT m Revision      
+couchPut_ db p = couchPutWith_ AG.encode (mkPath [db, p])
 
 -- | Brute force version of 'couchPut'. Creates a document regardless of 
 --   presence. 
 couchPut' :: (MonadCouch m, Data a) => 
-        Path        -- ^ Document path.
-     -> HT.Query    -- ^ Query arguments.
-     -> a           -- ^ The object to store.
-     -> ResourceT m Revision      
-couchPut' = couchPutWith' AG.encode
+       Path         -- ^ Database
+    -> Path         -- ^ Document path
+    -> Query    -- ^ Query arguments.
+    -> a           -- ^ The object to store.
+    -> ResourceT m Revision      
+couchPut' db p = couchPutWith' AG.encode (mkPath [db, p])
 
 ------------------------------------------------------------------------------
 -- View conduit
diff --git a/src/Database/CouchDB/Conduit/Implicit.hs b/src/Database/CouchDB/Conduit/Implicit.hs
new file mode 100644
--- /dev/null
+++ b/src/Database/CouchDB/Conduit/Implicit.hs
@@ -0,0 +1,69 @@
+-- | Implicit methods for CouchDB documents.
+--
+--   All implicit methods needs parser or encoder.
+
+module Database.CouchDB.Conduit.Implicit (
+     -- * Accessing documents
+    couchGet,
+    -- * Manipulating documents
+    couchPut,
+    couchPut_,
+    couchPut',
+) where
+
+import qualified Data.Aeson as A
+import qualified Data.ByteString.Lazy as BL (ByteString)
+import Data.Conduit (ResourceT)
+
+import Database.CouchDB.Conduit.Internal.Connection 
+        (MonadCouch(..), Path, mkPath, Revision)
+import Database.CouchDB.Conduit.Internal.Doc (couchGetWith, couchPutWith, 
+        couchPutWith_, couchPutWith')
+        
+import Network.HTTP.Types (Query)
+
+-- | Load CouchDB document and parse it with given parser.
+--
+-- > (rev, rawJson) <- couchGet Success "mydb" mydoc []
+couchGet :: MonadCouch m =>
+       (A.Value -> A.Result a)    -- ^ Parser
+    -> Path                       -- ^ Document path.
+    -> Path                       -- ^ Document path.
+    -> Query                      -- ^ Query
+    -> ResourceT m (Revision, a)
+couchGet f db p = couchGetWith f (mkPath [db, p])
+
+-- | Put document, with given encoder
+couchPut :: MonadCouch m =>
+      (a -> BL.ByteString)  -- ^ Encoder
+   -> Path                  -- ^ Document path.
+   -> Path                  -- ^ Document path.
+   -> Revision              -- ^ Document revision. For new docs provide 
+                            -- ^ empty string.
+   -> Query                 -- ^ Query arguments.
+   -> a                     -- ^ The object to store.
+   -> ResourceT m Revision
+couchPut f db p = couchPutWith f (mkPath [db, p])
+
+-- | \"Don't care\" version of 'couchPut'. Creates document only in its 
+--   absence.
+couchPut_ :: MonadCouch m =>
+      (a -> BL.ByteString)  -- ^ Encoder
+   -> Path                  -- ^ Document path.
+   -> Path                  -- ^ Document path.
+   -> Query                 -- ^ Query arguments.
+   -> a                     -- ^ The object to store.
+   -> ResourceT m Revision
+couchPut_ f db p = couchPutWith_ f (mkPath [db, p])
+
+-- | Brute force version of 'couchPut'. Creates a document regardless of 
+--   presence. 
+couchPut' :: MonadCouch m =>
+      (a -> BL.ByteString)  -- ^ Encoder
+   -> Path                  -- ^ Document path.
+   -> Path                  -- ^ Document path.
+   -> Query                 -- ^ Query arguments.
+   -> a                     -- ^ The object to store.
+   -> ResourceT m Revision
+couchPut' f db p = couchPutWith' f (mkPath [db, p])
+
diff --git a/src/Database/CouchDB/Conduit/Internal/Connection.hs b/src/Database/CouchDB/Conduit/Internal/Connection.hs
new file mode 100644
--- /dev/null
+++ b/src/Database/CouchDB/Conduit/Internal/Connection.hs
@@ -0,0 +1,163 @@
+{-# LANGUAGE DeriveDataTypeable #-}
+{-# LANGUAGE OverloadedStrings #-}
+{-# LANGUAGE FlexibleInstances #-}
+{-# LANGUAGE FlexibleContexts #-}
+
+-- | CouchDB connection. 
+
+module Database.CouchDB.Conduit.Internal.Connection (
+    -- * Document paths and revisions #path#
+    Path,
+    mkPath,
+    Revision,
+    
+    -- * CouchDB Connection #connection#
+    CouchConnection,
+    def,
+    couchHost,
+    couchPort,
+    couchManager,
+    couchLogin,
+    couchPass,
+    
+    -- * Runtime enviroment and errors #runtime#
+    MonadCouch (..),
+    CouchError (..),
+    runCouch,
+    withCouchConnection
+    
+) where
+
+import              Control.Monad.Trans.Reader (ReaderT, ask, runReaderT)
+import              Control.Exception (Exception)
+import              Control.Monad.Trans.Class (lift)
+
+import              Data.Conduit (ResourceIO, ResourceT, runResourceT)
+
+import qualified    Network.HTTP.Conduit as H
+import qualified    Network.HTTP.Types as HT
+
+import              Data.Generics (Typeable)
+import              Data.Default (Default (def))
+import qualified    Data.ByteString as B
+import qualified    Data.Text.Encoding as TE
+import qualified    Blaze.ByteString.Builder as BLB
+
+-----------------------------------------------------------------------------
+-- Paths
+-----------------------------------------------------------------------------
+
+-- | Represents a path or path fragment.
+--
+-- As a rule, full path to document in CouchDB is just URL path. But there is 
+-- one subtlety. For example, document ids /can/ contain slashes. But, 
+-- to work with such objects, path fragments must be escaped.
+-- 
+-- > database/doc%2Fname
+--
+-- But, fo non-document items such as views, attachments e.t.c., slashes
+-- between path fragments /must not/ be escaped. While slashes in path 
+-- fragments /must/ be escaped.
+-- 
+-- > database/_design/my%2Fdesign/_view/my%2Fview
+--
+-- Except low-level functions, @couchdb-conduit@ escapes all segments in paths.  
+type Path = B.ByteString
+
+-- | Represents a revision of a CouchDB Document. 
+type Revision = B.ByteString
+
+-- | Make correct path and escape fragments. Filter empty fragments.
+--
+-- > mkPath ["db", "", "doc/with/slashes"]
+-- > db/doc%2Fwith%2Fslashes
+mkPath :: [Path]    -- ^ Path fragments be escaped.  
+       -> Path
+mkPath = BLB.toByteString . HT.encodePathSegments . 
+    map TE.decodeUtf8 . filter (/="")
+
+-----------------------------------------------------------------------------
+-- Connection
+-----------------------------------------------------------------------------
+
+-- | Represents a single connection to CouchDB server. The constructor for this 
+--   data type is not exposed. Instead, you should use either the 'def' method 
+--   to retrieve a default instance.
+data CouchConnection = CouchConnection {
+      couchHost :: B.ByteString     
+        -- ^ Hostname. Default value is \"localhost\"
+    , couchPort :: Int              
+        -- ^ Port. 5984 by default.
+    , couchManager :: Maybe H.Manager  
+        -- ^ Connection 'Manager'. 'Nothing' by default. If you need to use
+        --   your 'H.Manager' (for connection pooling for example), set it to
+        --   'Just' 'H.Manager'.
+    , couchLogin :: B.ByteString
+        -- ^ CouchDB login. By default is 'B.empty'.
+    , couchPass :: B.ByteString
+        -- ^ CouchDB password. By default is 'B.empty'.
+}
+
+instance Default CouchConnection where
+    def = CouchConnection "localhost" 5984 Nothing B.empty B.empty
+
+-----------------------------------------------------------------------------
+-- Runtime
+-----------------------------------------------------------------------------
+
+-- | A monad which allows access to the connection.
+-- 
+-- All functions to access CouchDB require a 'MonadCouch' instance to 
+-- access the connection information.  'ReaderT' is an instance of 
+-- 'MonadCouch', and /runCouch/ runs a sequence of database actions using 
+-- 'ReaderT' and 'ResourceT'.
+-- 
+-- If your db code is part of a larger monad, it makes sense to just make the 
+-- larger monad an instance of 'MonadCouch' and skip the intermediate ReaderT, 
+-- since then performance is improved by eliminating one monad from the final 
+-- transformer stack.
+class ResourceIO m => MonadCouch m where
+    couchConnection :: m CouchConnection
+
+instance (ResourceIO m) => MonadCouch (ReaderT CouchConnection m) where
+    couchConnection = ask
+
+-- | A CouchDB Error.
+data CouchError 
+    = CouchHttpError Int B.ByteString
+        -- ^ Error comes from http.
+    | CouchInternalError B.ByteString
+        -- ^ Non-http errors include things like errors  
+        --   parsing the response.
+    | NotModified
+        -- ^ /Is not an error actually/. It is thrown when CouchDB returns 
+        --   @304 - Not Modified@ response to the request. See 
+        --   <http://wiki.apache.org/couchdb/HTTP_Document_API>
+  deriving (Show, Typeable)
+instance Exception CouchError
+
+-- | Run a sequence of CouchDB actions. This function is a combination of 
+--   'withCouchConnection', 'runReaderT' and 'runResourceT'.
+--  
+--   If you create your own instance of 'MonadCouch', use 'withCouchConnection'.  
+runCouch :: ResourceIO m =>
+       CouchConnection                            -- ^ Couch connection
+    -> ResourceT (ReaderT CouchConnection m) a    -- ^ CouchDB actions
+    -> m a
+runCouch c = withCouchConnection c . runReaderT . runResourceT
+
+-- | Connect to a CouchDB server, call the supplied function, and then close 
+--   the connection.
+-- 
+-- > withCouchConnection def {couchDB = "db"} . runReaderT . runResourceT $ do
+-- >    ... -- actions
+withCouchConnection :: ResourceIO m =>
+       CouchConnection              -- ^ Couch connection
+    -> (CouchConnection -> m a)     -- ^ Function to run
+    -> m a
+withCouchConnection c@(CouchConnection _ _ mayMan  _ _) f = 
+    case mayMan of
+        -- Allocate manager with helper
+        Nothing -> H.withManager $ \m -> lift $ f $ c {couchManager = Just m}
+        _ -> f c
+
diff --git a/src/Database/CouchDB/Conduit/Internal/Doc.hs b/src/Database/CouchDB/Conduit/Internal/Doc.hs
--- a/src/Database/CouchDB/Conduit/Internal/Doc.hs
+++ b/src/Database/CouchDB/Conduit/Internal/Doc.hs
@@ -1,6 +1,6 @@
 {-# LANGUAGE OverloadedStrings #-}
 
--- | Internal
+-- | Internal doc.
 module Database.CouchDB.Conduit.Internal.Doc (
     couchRev,
     couchRev',
@@ -25,9 +25,10 @@
 import qualified    Network.HTTP.Conduit as H
 import              Network.HTTP.Types as HT
 
-import              Database.CouchDB.Conduit
-import              Database.CouchDB.Conduit.LowLevel (couch')
+import              Database.CouchDB.Conduit.Internal.Connection
+import              Database.CouchDB.Conduit.LowLevel (couch, protect')
 import              Database.CouchDB.Conduit.Internal.Parser
+import Control.Monad (void)
 
 ------------------------------------------------------------------------------
 -- Type-independent methods
@@ -35,19 +36,20 @@
 
 -- | Get Revision of a document. 
 couchRev :: MonadCouch m => 
-       Path                 -- ^ Path
+       Path                 -- ^ Correct 'Path' with escaped fragments.
     -> ResourceT m Revision
 couchRev p = do
-    (H.Response _ hs _) <- couch' HT.methodHead p [] [] 
-                                (H.RequestBodyBS B.empty)
+    (H.Response _ hs _) <- couch HT.methodHead 
+                                 p [] [] 
+                                 (H.RequestBodyBS B.empty) protect' 
     return $ peekRev hs        
   where
     peekRev = B.tail . B.init . fromJust . lookup "Etag"
 
 -- | Brain-free version of 'couchRev'. If document absent, 
 --   just return 'B.empty'.
-couchRev' :: MonadCouch m =>
-       Path 
+couchRev' :: MonadCouch m =>
+       Path                 -- ^ Correct 'Path' with escaped fragments.
     -> ResourceT m Revision
 couchRev' p = 
     catch (couchRev p) handler404
@@ -57,43 +59,46 @@
 
 -- | Delete the given revision of the object.    
 couchDelete :: MonadCouch m => 
-       Path 
-    -> Revision
+       Path                 -- ^ Correct 'Path' with escaped fragments.
+    -> Revision             -- ^ Revision
     -> ResourceT m ()
-couchDelete p r = couch' HT.methodDelete p [] [("rev", Just r)]
-               (H.RequestBodyBS B.empty) 
-               >> return ()
+couchDelete p r = void $
+  couch methodDelete p 
+        [] [("rev", Just r)]
+        (H.RequestBodyBS B.empty) protect'
                
 ------------------------------------------------------------------------------
 -- with converter
 ------------------------------------------------------------------------------
 
 -- | Load CouchDB document and parse it with given parser.  
-couchGetWith :: MonadCouch m =>
-          (A.Value -> A.Result a)       -- ^ Parser
-       -> Path                          -- ^ Path
-       -> Query                         -- ^ Query
+couchGetWith :: MonadCouch m =>
+          (A.Value -> A.Result a)    -- ^ Parser
+       -> Path                       -- ^ Correct 'Path' with escaped fragments.
+       -> Query                      -- ^ Query
        -> ResourceT m (Revision, a)
 couchGetWith f p q = do
-    H.Response _ _ bsrc <- couch' HT.methodGet p [] q 
-                            (H.RequestBodyBS B.empty)
+    H.Response _ _ bsrc <- couch HT.methodGet 
+                                 p [] q 
+                                 (H.RequestBodyBS B.empty) protect'
     j <- bsrc $$ CA.sinkParser A.json
     A.String r <- lift $ either resourceThrow return $ extractField "_rev" j
     o <- lift $ jsonToTypeWith f j 
     return (TE.encodeUtf8 r, o)
 
 -- | Put document, with given encoder
-couchPutWith :: MonadCouch m =>
-          (a -> BL.ByteString)  -- ^ Encoder
-       -> Path                  -- ^ Document path. 
-       -> Revision              -- ^ Document revision. For new docs provide 
-                                -- ^ empty string.
-       -> Query                 -- ^ Query arguments.
-       -> a                     -- ^ The object to store.
-       -> ResourceT m Revision
-couchPutWith f p r q val = do
-    H.Response _ _ bsrc <- couch' HT.methodPut p (ifMatch r) q 
-            (H.RequestBodyLBS $ f val)
+couchPutWith :: MonadCouch m =>
+      (a -> BL.ByteString)  -- ^ Encoder
+   -> Path                  -- ^ Correct 'Path' with escaped fragments.
+   -> Revision              -- ^ Document revision. For new docs provide 
+                            -- ^ empty string.
+   -> Query                 -- ^ Query arguments.
+   -> a                     -- ^ The object to store.
+   -> ResourceT m Revision
+couchPutWith f p r q val = do
+    H.Response _ _ bsrc <- couch HT.methodPut 
+                                 p (ifMatch r) q 
+                                 (H.RequestBodyLBS $ f val) protect'
     j <- bsrc $$ CA.sinkParser A.json
     lift $ either resourceThrow return $ extractRev j
   where 
@@ -103,11 +108,11 @@
 -- | \"Don't care\"  version of version of 'couchPutWith'. Stores 
 --   document only if it not exists.
 couchPutWith_ :: MonadCouch m => 
-        (a -> BL.ByteString)  -- ^ Encoder
-     -> Path        -- ^ Document path.
-     -> HT.Query    -- ^ Query arguments.
-     -> a           -- ^ The object to store.
-     -> ResourceT m Revision      
+      (a -> BL.ByteString)  -- ^ Encoder
+   -> Path                  -- ^ Correct 'Path' with escaped fragments.
+   -> HT.Query              -- ^ Query arguments.
+   -> a                     -- ^ The object to store.
+   -> ResourceT m Revision      
 couchPutWith_ f p q val = do
     rev <- couchRev' p
     if rev == "" 
@@ -116,11 +121,11 @@
 
 -- | Brute force version of 'couchPutWith'.
 couchPutWith' :: MonadCouch m => 
-        (a -> BL.ByteString)  -- ^ Encoder
-     -> Path        -- ^ Document path.
-     -> HT.Query    -- ^ Query arguments.
-     -> a           -- ^ The object to store.
-     -> ResourceT m Revision      
+      (a -> BL.ByteString)  -- ^ Encoder
+   -> Path                  -- ^ Correct 'Path' with escaped fragments.
+   -> HT.Query              -- ^ Query arguments.
+   -> a                     -- ^ The object to store.
+   -> ResourceT m Revision      
 couchPutWith' f p q val = do
     rev <- couchRev' p
     couchPutWith f p rev q val
diff --git a/src/Database/CouchDB/Conduit/Internal/Parser.hs b/src/Database/CouchDB/Conduit/Internal/Parser.hs
--- a/src/Database/CouchDB/Conduit/Internal/Parser.hs
+++ b/src/Database/CouchDB/Conduit/Internal/Parser.hs
@@ -9,7 +9,8 @@
 import qualified    Data.HashMap.Lazy as M
 import qualified    Data.Aeson as A
 
-import              Database.CouchDB.Conduit
+import              Database.CouchDB.Conduit.Internal.Connection 
+                        (CouchError(..), Revision)
 
 extractField :: T.Text -> A.Value -> Either CouchError A.Value
 extractField s (A.Object o) = 
@@ -31,7 +32,7 @@
              -> A.Value 
              -> m a
 jsonToTypeWith f j = case f j of
-        A.Error e -> resourceThrow $ CouchInternalError $ BU8.fromString $
-                        ("Error parsing json: " ++ e)
+        A.Error e -> resourceThrow $ CouchInternalError $ 
+                        BU8.fromString ("Error parsing json: " ++ e)
         A.Success o -> return o
 
diff --git a/src/Database/CouchDB/Conduit/Internal/View.hs b/src/Database/CouchDB/Conduit/Internal/View.hs
--- a/src/Database/CouchDB/Conduit/Internal/View.hs
+++ b/src/Database/CouchDB/Conduit/Internal/View.hs
@@ -6,7 +6,8 @@
 import qualified    Data.Conduit.List as CL (mapM)
 import Data.ByteString.Char8 (pack)
 
-import              Database.CouchDB.Conduit
+import              Database.CouchDB.Conduit.Internal.Connection 
+                        (CouchError(..))
 
 -- | Convert CouchDB view row or row value from 'Database.CouchDB.Conduit.View' 
 --   to concrete type.
diff --git a/src/Database/CouchDB/Conduit/LowLevel.hs b/src/Database/CouchDB/Conduit/LowLevel.hs
--- a/src/Database/CouchDB/Conduit/LowLevel.hs
+++ b/src/Database/CouchDB/Conduit/LowLevel.hs
@@ -6,7 +6,6 @@
 module Database.CouchDB.Conduit.LowLevel (
     CouchResponse,
     couch,
-    couch',
     protect,
     protect'
 ) where
@@ -32,7 +31,7 @@
 import qualified    Network.HTTP.Conduit as H
 import qualified    Network.HTTP.Types as HT
 
-import              Database.CouchDB.Conduit
+import              Database.CouchDB.Conduit.Internal.Connection
 
 -- | CouchDB response
 type CouchResponse m = H.Response (Source m B.ByteString)
@@ -43,21 +42,21 @@
 --   attachments that are not in JSON format.
 couch :: MonadCouch m =>
        HT.Method                -- ^ Method
-    -> (Path -> Path)           -- ^ Path creation function
+    -> Path                     -- ^ Correct 'Path' with escaped fragments.
     -> HT.RequestHeaders        -- ^ Headers
     -> HT.Query                 -- ^ Query args
     -> H.RequestBody m          -- ^ Request body
     -> (CouchResponse m -> ResourceT m (CouchResponse m))
                                 -- ^ Protect function. See 'protect'
     -> ResourceT m (CouchResponse m)
-couch meth pathFn hdrs qs reqBody protectFn = do
+couch meth path hdrs qs reqBody protectFn = do
     conn <- lift couchConnection
     let req = H.def 
             { H.method          = meth
             , H.host            = couchHost conn
             , H.requestHeaders  = hdrs
             , H.port            = couchPort conn
-            , H.path            = pathFn $ couchDB conn
+            , H.path            = path
             , H.queryString     = HT.renderQuery False qs
             , H.requestBody     = reqBody
             , H.checkStatus = const . const $ Nothing }
@@ -66,23 +65,6 @@
             (couchLogin conn) (couchPass conn) req
     res <- H.http req' (fromJust $ couchManager conn)
     protectFn res
-
--- | Simplified version of 'couch'. This version uses standart path 
---   creation and protect functions.
-couch' :: MonadCouch m =>
-       HT.Method                -- ^ Method
-    -> Path                     -- ^ Path
-    -> HT.RequestHeaders        -- ^ Headers
-    -> HT.Query                 -- ^ Query args
-    -> H.RequestBody m          -- ^ Request body
-    -> ResourceT m (CouchResponse m)
-couch' meth p hdrs qs reqBody = 
-        couch meth 
-        (\dbP -> B.intercalate "/" . filter (/="") $ [dbP, p])
-        hdrs
-        qs
-        reqBody
-        protect'   
 
 -- | Protect 'H.Response' from bad status codes. If status code in list 
 --   of status codes - just return response. Otherwise - throw 'CouchError'.
diff --git a/src/Database/CouchDB/Conduit/View.hs b/src/Database/CouchDB/Conduit/View.hs
--- a/src/Database/CouchDB/Conduit/View.hs
+++ b/src/Database/CouchDB/Conduit/View.hs
@@ -31,8 +31,8 @@
 import qualified    Network.HTTP.Conduit as H
 import qualified    Network.HTTP.Types as HT
 
-import              Database.CouchDB.Conduit
-import              Database.CouchDB.Conduit.LowLevel (couch')
+import              Database.CouchDB.Conduit.Internal.Connection
+import              Database.CouchDB.Conduit.LowLevel (couch, protect')
 
 -----------------------------------------------------------------------------
 -- Running
@@ -56,45 +56,47 @@
 -- > runCouch def {couchDB="mydb"} $ do
 -- >
 -- >     -- Print all upon receipt.
--- >     src <- couchView "mydesign" "myview" [] 
+-- >     src <- couchView "mydb" "mydesign" "myview" [] 
 -- >     src $$ CL.mapM_ (liftIO . print)
 -- >
 -- >     -- ... Or extract row value and consume
--- >     src' <- couchView "mydesign" "myview" [] 
+-- >     src' <- couchView "mydb" "mydesign" "myview" [] 
 -- >     res <- src' $= rowValue $$ CL.consume
 couchView :: MonadCouch m =>
-       Path                 -- ^ Design document
-    -> Path                 -- ^ View name
+       Path                 -- ^ Database
+    -> Path                 -- ^ Design document
+    -> Path                 -- ^ View name
     -> HT.Query             -- ^ Query parameters
     -> ResourceT m (Source m A.Object)
-couchView designDocName viewName q = do
-    H.Response _ _ bsrc <- couch' HT.methodGet fullPath [] q 
-        (H.RequestBodyBS B.empty)
+couchView db designDocName viewName q = do
+    H.Response _ _ bsrc <- couch HT.methodGet fullPath [] q 
+        (H.RequestBodyBS B.empty) protect'
     return $ bsrc $= conduitCouchView
   where
-    fullPath = B.concat ["_design/", designDocName, "/_view/", viewName]
+    fullPath = mkPath [db, "_design", designDocName, "_view", viewName]
 
--- | Brain-free version of 'couchView'. Takes 'Sink' to consume response.
---
+-- | Brain-free version of 'couchView'. Takes 'Sink' to consume response.
+--
 -- > runCouch def {couchDB="mydb"} $ do
--- >
--- >     -- Print all upon receipt.
+-- >
+-- >     -- Print all upon receipt.
 -- >     couchView' "mydesign" "myview" [] $ CL.mapM_ (liftIO . print)
 -- >
 -- >     -- ... Or extract row value and consume
--- >     res <- couchView' "mydesign" "myview" [] $ rowValue =$ CL.consume
-couchView' :: MonadCouch m =>
-       Path                 -- ^ Design document
+-- >     res <- couchView' "mydesign" "myview" [] $ rowValue =$ CL.consume
+couchView' :: MonadCouch m =>
+       Path                 -- ^ Database
+    -> Path                 -- ^ Design document
     -> Path                 -- ^ View name
     -> HT.Query             -- ^ Query parameters
     -> Sink A.Object m a    -- ^ Sink for handle view rows.
     -> ResourceT m a
-couchView' designDocName viewName q sink = do
-    H.Response _ _ bsrc <- couch' HT.methodGet fullPath [] q 
-        (H.RequestBodyBS B.empty)
+couchView' db designDocName viewName q sink = do
+    H.Response _ _ bsrc <- couch HT.methodGet fullPath [] q 
+        (H.RequestBodyBS B.empty) protect'
     bsrc $= conduitCouchView $$ sink
   where
-    fullPath = mkPath ["_design", designDocName, "_view", viewName]
+    fullPath = mkPath [db, "_design", designDocName, "_view", viewName]
 
 -- | Conduit for extract \"value\" field from CouchDB view row.
 rowValue :: ResourceIO m => Conduit A.Object m A.Value
diff --git a/test/Database/CouchDB/Conduit/Test/Base.hs b/test/Database/CouchDB/Conduit/Test/Base.hs
--- a/test/Database/CouchDB/Conduit/Test/Base.hs
+++ b/test/Database/CouchDB/Conduit/Test/Base.hs
@@ -31,16 +31,15 @@
 -- | Just connect
 case_justConnect :: Assertion
 case_justConnect = runCouch def $ do
-    H.Response (HT.Status sc _) _h _bsrc <- couch' HT.methodGet "" [] [] 
-                    (H.RequestBodyBS B.empty)
+    H.Response (HT.Status sc _) _h _bsrc <- couch HT.methodGet "" [] [] 
+                    (H.RequestBodyBS B.empty) protect'
     liftIO $ sc @=? 200
 
 -- | Put and delete
 case_dbPut :: Assertion    
 case_dbPut =  runCouch def {couchLogin = login, 
-                            couchPass=pass,
-                            couchDB="cdbc_dbputdel"} $ do
-    couchPutDB_
-    couchDeleteDB
+                            couchPass=pass} $ do
+    couchPutDB_ "cdbc_dbputdel"
+    couchDeleteDB "cdbc_dbputdel"
     
     
diff --git a/test/Database/CouchDB/Conduit/Test/Explicit.hs b/test/Database/CouchDB/Conduit/Test/Explicit.hs
--- a/test/Database/CouchDB/Conduit/Test/Explicit.hs
+++ b/test/Database/CouchDB/Conduit/Test/Explicit.hs
@@ -39,26 +39,26 @@
 case_justPutGet :: Assertion
 case_justPutGet = bracket_
     setup teardown $
-    runCouch (conn dbName) $ do
-        rev <- couchPut "doc-just" "" [] $ TestDoc "doc" 1 "1"
-        rev' <- couchPut "doc-just" rev [] $ TestDoc "doc" 2 "2"
-        rev'' <- couchRev "doc-just"
+    runCouch conn $ do
+        rev <- couchPut dbName "doc-just" "" [] $ TestDoc "doc" 1 "1"
+        rev' <- couchPut dbName "doc-just" rev [] $ TestDoc "doc" 2 "2"
+        rev'' <- couchRev dbName "doc-just"
         liftIO $ rev' @=? rev''
-        couchDelete "doc-just" rev''
+        couchDelete dbName "doc-just" rev''
 
 case_massFlow :: Assertion
 case_massFlow = bracket_
     setup teardown $
-    runCouch (conn dbName) $ do
+    runCouch conn $ do
         revs <- mapM (\n -> 
-                couchPut (docn n) "" [] $ TestDoc "doc" n $ show n
+                couchPut dbName (docn n) "" [] $ TestDoc "doc" n $ show n
             ) [1..100]
         liftIO $ length revs @=? 100
-        revs' <- mapM (\n -> couchRev $ docn n) [1..100]
+        revs' <- mapM (\n -> couchRev dbName $ docn n) [1..100]
         liftIO $ revs @=? revs'
         liftIO $ length revs' @=? 100
         mapM_ (\(n,r) ->
-            couchDelete (docn n) r) $ zip [1..100] revs'
+            couchDelete dbName (docn n) r) $ zip [1..100] revs'
   where
     docn n = fromString $ "doc-" ++ show (n :: Int)    
 
@@ -66,17 +66,17 @@
 case_massIter :: Assertion
 case_massIter = bracket_
     setup teardown $
-    runCouch (conn dbName) $ 
+    runCouch conn $ 
         mapM_ (\n -> do
             let name = docn n 
             let d = TestDoc "doc" n $ show n
-            rev <- couchPut name "" [] d
-            couchDelete (docn n) rev
-            _ <- couchPut name "" [] d
-            rev'' <- couchPut' name [] d
-            (_, d') <- couchGet name []
+            rev <- couchPut dbName name "" [] d
+            couchDelete dbName (docn n) rev
+            _ <- couchPut dbName name "" [] d
+            rev'' <- couchPut' dbName name [] d
+            (_, d') <- couchGet dbName name []
             liftIO $ d @=? d'
-            couchDelete (docn n) rev''
+            couchDelete dbName (docn n) rev''
          ) [1..100]
   where
     docn n = fromString $ "doc-" ++ show (n :: Int) 
diff --git a/test/Database/CouchDB/Conduit/Test/Generic.hs b/test/Database/CouchDB/Conduit/Test/Generic.hs
--- a/test/Database/CouchDB/Conduit/Test/Generic.hs
+++ b/test/Database/CouchDB/Conduit/Test/Generic.hs
@@ -32,26 +32,26 @@
 case_justPutGet :: Assertion
 case_justPutGet = bracket_
     setup teardown $ 
-    runCouch (conn dbName) $ do
-        rev <- couchPut "doc-just" "" [] $ TestDoc "doc" 1 "1"
-        rev' <- couchPut "doc-just" rev [] $ TestDoc "doc" 2 "2"
-        rev'' <- couchRev "doc-just"
+    runCouch conn $ do
+        rev <- couchPut dbName "doc-just" "" [] $ TestDoc "doc" 1 "1"
+        rev' <- couchPut dbName "doc-just" rev [] $ TestDoc "doc" 2 "2"
+        rev'' <- couchRev dbName "doc-just"
         liftIO $ rev' @=? rev''
-        couchDelete "doc-just" rev''
+        couchDelete dbName "doc-just" rev''
 
 case_massFlow :: Assertion
 case_massFlow = bracket_
     setup teardown $ 
-    runCouch (conn dbName) $ do
+    runCouch conn $ do
         revs <- mapM (\n -> 
-                couchPut (docn n) "" [] $ TestDoc "doc" n $ show n
+                couchPut dbName (docn n) "" [] $ TestDoc "doc" n $ show n
             ) [1..100]
         liftIO $ length revs @=? 100
-        revs' <- mapM (\n -> couchRev $ docn n) [1..100]
+        revs' <- mapM (\n -> couchRev dbName $ docn n) [1..100]
         liftIO $ revs @=? revs'
         liftIO $ length revs' @=? 100
         mapM_ (\(n,r) ->
-            couchDelete (docn n) r) $ zip [1..100] revs'
+            couchDelete dbName (docn n) r) $ zip [1..100] revs'
   where
     docn n = fromString $ "doc-" ++ show (n :: Int)    
 
@@ -59,17 +59,17 @@
 case_massIter :: Assertion
 case_massIter = bracket_
     setup teardown $ 
-    runCouch (conn dbName) $ 
+    runCouch conn $ 
         mapM_ (\n -> do
             let name = docn n 
             let d = TestDoc "doc" n $ show n
-            rev <- couchPut name "" [] d
-            couchDelete (docn n) rev
-            _ <- couchPut name "" [] d
-            rev'' <- couchPut' name [] d
-            (_, d') <- couchGet name []
+            rev <- couchPut dbName name "" [] d
+            couchDelete dbName (docn n) rev
+            _ <- couchPut dbName name "" [] d
+            rev'' <- couchPut' dbName name [] d
+            (_, d') <- couchGet dbName name []
             liftIO $ d @=? d'
-            couchDelete (docn n) rev''
+            couchDelete dbName (docn n) rev''
          ) [1..100]
   where
     docn n = fromString $ "doc-" ++ show (n :: Int)
diff --git a/test/Database/CouchDB/Conduit/Test/Util.hs b/test/Database/CouchDB/Conduit/Test/Util.hs
--- a/test/Database/CouchDB/Conduit/Test/Util.hs
+++ b/test/Database/CouchDB/Conduit/Test/Util.hs
@@ -10,14 +10,13 @@
 import CouchDBAuth
 
 setupDB :: ByteString -> IO ()
-setupDB n = runCouch (conn n) $ couchPutDB_
+setupDB n = runCouch conn $ couchPutDB_ n
 
 tearDB :: ByteString -> IO ()
-tearDB n = runCouch (conn n) $ couchDeleteDB
+tearDB n = runCouch conn $ couchDeleteDB n
 
 -- | Connection connection. See readme
-conn :: Path -> CouchConnection
-conn db = def {
-    couchDB = db, 
+conn :: CouchConnection
+conn = def {
     couchLogin = login,
     couchPass = pass}
diff --git a/test/Database/CouchDB/Conduit/Test/View.hs b/test/Database/CouchDB/Conduit/Test/View.hs
--- a/test/Database/CouchDB/Conduit/Test/View.hs
+++ b/test/Database/CouchDB/Conduit/Test/View.hs
@@ -52,24 +52,24 @@
 case_createView :: Assertion
 case_createView = bracket_
     (setupDB db)
-    (tearDB db) $ runCouch (conn db) $ do
-        rev <- couchPutView' "mydesign" "myview"
+    (tearDB db) $ runCouch conn $ do
+        rev <- couchPutView' db "mydesign" "myview"
             "function(doc){emit(null, doc);}" Nothing
-        rev' <- CCG.couchRev "_design/mydesign"
+        rev' <- couchRev db "_design/mydesign"
         liftIO $ rev @=? rev' 
   where 
     db = "cdbc_test_view_create"
 
 case_bigValues :: Assertion
 case_bigValues = bracket_
-    (runCouch (conn db) $ do
-        couchPutDB_
-        _ <- couchPutView' "mydesign" "myview"
+    (runCouch conn $ do
+        couchPutDB_ db
+        _ <- couchPutView' db "mydesign" "myview"
                 "function(doc){emit(doc.intV, doc);}" Nothing
-        mapM_ (\n -> CCG.couchPut' (docName n) [] $ doc n) [1..20]
+        mapM_ (\n -> CCG.couchPut' db (docName n) [] $ doc n) [1..20]
     )
-    (tearDB db) $ runCouch (conn db) $ do
-        res <- couchView' "mydesign" "myview" [] $ 
+    (tearDB db) $ runCouch conn $ do
+        res <- couchView' db "mydesign" "myview" [] $ 
             (rowValue =$= CCG.toType) =$ CL.consume 
         mapM_ (\(a, b) -> liftIO $ a @=? doc b) $ zip res [1..20]
   where 
@@ -80,14 +80,14 @@
 
 case_withReduce :: Assertion    
 case_withReduce = bracket_
-    (runCouch (conn db) $ do
-        couchPutDB_
-        _ <- couchPutView' "mydesign" "myview"
+    (runCouch conn $ do
+        couchPutDB_ db
+        _ <- couchPutView' db "mydesign" "myview"
                 "function(doc){emit(doc.intV, doc.intV);}" 
                 $ Just "function(keys, values){return sum(values);}"
-        mapM_ (\n -> CCG.couchPut' (docName n) [] $ doc n) [1..20])
-    (tearDB db) $ runCouch (conn db) $ do
-        res <- couchView' "mydesign" "myview" [] $
+        mapM_ (\n -> CCG.couchPut' db (docName n) [] $ doc n) [1..20])
+    (tearDB db) $ runCouch conn $ do
+        res <- couchView' db "mydesign" "myview" [] $
             (rowValue =$= CCG.toType) =$ CL.consume
         liftIO $ res @=? [ReducedView 210]
   where
