diff --git a/README.md b/README.md
--- a/README.md
+++ b/README.md
@@ -7,7 +7,7 @@
 
 Badges
 ------
-[![Travis (.com) branch](https://img.shields.io/travis/com/haskell-linnet/linnet/master?style=flat-square)](https://travis-ci.com/haskell-linnet/linnet) [![Gitter](https://img.shields.io/gitter/room/haskell-linnet/community?style=flat-square)](https://gitter.im/haskell-linnet/community) [![Hackage](https://img.shields.io/hackage/v/linnet?style=flat-square])](http://hackage.haskell.org/package/linnet)
+[![Travis (.com) branch](https://img.shields.io/travis/com/haskell-linnet/linnet/master?style=flat-square)](https://travis-ci.com/haskell-linnet/linnet) [![Gitter](https://img.shields.io/gitter/room/haskell-linnet/community?style=flat-square)](https://gitter.im/haskell-linnet/community) [![Hackage](https://img.shields.io/hackage/v/linnet?style=flat-square)](http://hackage.haskell.org/package/linnet)
 
 Hello world
 -----------
diff --git a/linnet.cabal b/linnet.cabal
--- a/linnet.cabal
+++ b/linnet.cabal
@@ -1,6 +1,6 @@
 cabal-version: 1.12
 name: linnet
-version: 0.1.0.2
+version: 0.2.0.0
 license: Apache
 license-file: LICENSE
 copyright: 2019 Sergey Kolbasov
@@ -42,6 +42,7 @@
         Linnet.Input
         Linnet.Internal.Coproduct
         Linnet.Internal.HList
+        Linnet.NaturalTransformation
         Linnet.Output
         Linnet.ToResponse
     hs-source-dirs: src
@@ -56,7 +57,6 @@
         either >=5.0.1.1,
         exceptions >=0.10.2,
         http-types >=0.12.3,
-        io-streams >=1.5.1.0,
         mtl >=2.2.2,
         text >=1.2.3.1,
         transformers >=0.5.6.2,
@@ -96,7 +96,6 @@
         exceptions >=0.10.2,
         hspec >=2.7.1,
         http-types >=0.12.3,
-        io-streams >=1.5.1.0,
         linnet -any,
         mtl >=2.2.2,
         quickcheck-classes >=0.6.1.0,
diff --git a/src/Linnet/Bootstrap.hs b/src/Linnet/Bootstrap.hs
--- a/src/Linnet/Bootstrap.hs
+++ b/src/Linnet/Bootstrap.hs
@@ -16,14 +16,15 @@
   , toApp
   ) where
 
-import           Control.Monad.Reader      (ReaderT (..))
-import           Data.Data                 (Proxy)
-import           GHC.Base                  (Symbol)
-import qualified Linnet.Compile            as Compile
+import           Control.Monad.Reader         (ReaderT (..))
+import           Data.Data                    (Proxy)
+import           GHC.Base                     (Symbol)
+import qualified Linnet.Compile               as Compile
 import           Linnet.Endpoint
-import           Linnet.Internal.Coproduct (CNil, Coproduct)
-import           Linnet.Internal.HList     (HList (..))
-import           Network.Wai               (Application, Request, Response)
+import           Linnet.Internal.Coproduct    (CNil, Coproduct)
+import           Linnet.Internal.HList        (HList (..))
+import           Linnet.NaturalTransformation
+import           Network.Wai                  (Application, Request, Response)
 
 newtype Bootstrap (m :: * -> *) cts es =
   Bootstrap es
@@ -68,5 +69,5 @@
 --  * @ReaderT RequestContext IO@ could be used to pass some data as local context for the request.
 --
 --  * Some monad for logging (i.e. co-log)
-toApp :: (forall a. m a -> IO a) -> ReaderT Request m Response -> Application
-toApp toIO !readerT request callback = toIO (runReaderT readerT request) >>= callback
+toApp :: forall m . (NaturalTransformation m IO) => ReaderT Request m Response -> Application
+toApp !readerT request callback = mapK (runReaderT readerT request) >>= callback
diff --git a/src/Linnet/Endpoints/Bodies.hs b/src/Linnet/Endpoints/Bodies.hs
--- a/src/Linnet/Endpoints/Bodies.hs
+++ b/src/Linnet/Endpoints/Bodies.hs
@@ -24,7 +24,7 @@
 import           Linnet.Input
 import           Linnet.Output
 import           Network.Wai             (RequestBodyLength (..),
-                                          lazyRequestBody, requestBodyLength)
+                                          requestBodyLength, strictRequestBody)
 
 decodeBody ::
      forall ct a m. (Decode ct a, MonadThrow m)
@@ -54,7 +54,7 @@
             KnownLength _ ->
               Matched
                 { matchedReminder = input
-                , matchedOutput = (liftIO . lazyRequestBody . request) input >>= decodeBody @ct @a
+                , matchedOutput = (liftIO . strictRequestBody . request) input >>= decodeBody @ct @a
                 }
     , toString = "body"
     }
@@ -76,7 +76,8 @@
             KnownLength _ ->
               Matched
                 { matchedReminder = input
-                , matchedOutput = (fmap . fmap) Just ((liftIO . lazyRequestBody . request) input >>= decodeBody @ct @a)
+                , matchedOutput =
+                    (fmap . fmap) Just ((liftIO . strictRequestBody . request) input >>= decodeBody @ct @a)
                 }
     , toString = "bodyMaybe"
     }
diff --git a/src/Linnet/NaturalTransformation.hs b/src/Linnet/NaturalTransformation.hs
new file mode 100644
--- /dev/null
+++ b/src/Linnet/NaturalTransformation.hs
@@ -0,0 +1,10 @@
+{-# LANGUAGE MultiParamTypeClasses #-}
+
+module Linnet.NaturalTransformation where
+
+-- | Type class that defines transformation F a -> G a used by Linnet to convert custom monads to WAI IO
+class NaturalTransformation f g where
+  mapK :: f a -> g a
+
+instance NaturalTransformation IO IO where
+  mapK = id
diff --git a/src/Linnet/ToResponse.hs b/src/Linnet/ToResponse.hs
--- a/src/Linnet/ToResponse.hs
+++ b/src/Linnet/ToResponse.hs
@@ -26,7 +26,7 @@
 class ToResponse (ct :: Symbol) a where
   toResponse :: a -> Response
 
-instance (ToResponse' (ValueT a) ct a) => ToResponse ct a where
+instance {-# OVERLAPPABLE #-} (ToResponse' (ValueT a) ct a) => ToResponse ct a where
   toResponse = toResponse' @(ValueT a) @ct
 
 class ToResponse' (value :: Value) (ct :: Symbol) a where
diff --git a/test/BootstrapSpec.hs b/test/BootstrapSpec.hs
--- a/test/BootstrapSpec.hs
+++ b/test/BootstrapSpec.hs
@@ -71,7 +71,7 @@
   it "compiles into WAI application" $
     property $ \(out :: (Output T.Text)) ->
       monadicIO $ do
-        let app = bootstrap @TextPlain (liftOutputM (return out)) & compile & toApp id
+        let app = bootstrap @TextPlain (liftOutputM (return out)) & compile & toApp @IO
         mvar <- liftIO newEmptyMVar
         let callback req = ResponseReceived <$ putMVar mvar req
         _ <- liftIO $ app defaultRequest callback
