diff --git a/CHANGELOG.md b/CHANGELOG.md
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -3,6 +3,10 @@
 `di-polysemy` uses [PVP Versioning][1].
 The changelog is available [on GitHub][2].
 
+## 0.1.4.0
+
+* `runDiToIOFinal` and `runDiToStderrIOFinal` have been added
+
 ## 0.1.3.0
 
 * The 'Reset' action has been added
diff --git a/di-polysemy.cabal b/di-polysemy.cabal
--- a/di-polysemy.cabal
+++ b/di-polysemy.cabal
@@ -4,10 +4,10 @@
 --
 -- see: https://github.com/sol/hpack
 --
--- hash: 28b2f36f02478805bfe9c6d2da769eb470c6bd9e31b6ad61b9f28c5b6ac5f7a6
+-- hash: 7d5a66b6c7f2d80869176c92262777e8ff5e62c94a600d922c5ee4a2d4a75b77
 
 name:           di-polysemy
-version:        0.1.3.1
+version:        0.1.4.0
 synopsis:       DI logger wrapped for Polysemy
 description:    Please see the README on GitHub at <https://github.com/nitros12/di-polysemy>
 category:       Logging
diff --git a/src/DiPolysemy.hs b/src/DiPolysemy.hs
--- a/src/DiPolysemy.hs
+++ b/src/DiPolysemy.hs
@@ -2,6 +2,8 @@
     ( Di(..)
     , runDiToIO
     , runDiToStderrIO
+    , runDiToIOFinal
+    , runDiToStderrIOFinal
     , log
     , flush
     , local
@@ -38,6 +40,9 @@
 import qualified Polysemy.Reader as P
 
 import           Prelude                    hiding ( error, log )
+import Control.Concurrent (takeMVar, MVar, putMVar, newEmptyMVar)
+import Polysemy.Async (asyncToIOFinal, async)
+import Polysemy.Resource (resourceToIOFinal, bracket)
 
 data Di level path msg m a where
   Log    :: level -> msg -> Di level path msg m ()
@@ -69,33 +74,64 @@
 
 type DiR level msg = (DC.Di level Df1.Path msg, DC.Di level Df1.Path msg)
 
+interpretDi :: forall r a level msg. Members '[Embed IO, P.Reader (DiR level msg)] r
+      => Sem (Di level Df1.Path msg ': r) a
+      -> Sem r a
+interpretDi = interpretH $ \case
+      Log level msg -> do
+        (_, di) <- P.ask @(DiR level msg)
+        (embed @IO $ DC.log di level msg) >>= pureT
+      Flush         -> do
+        (_, di) <- P.ask @(DiR level msg)
+        (embed @IO $ DC.flush di) >>= pureT
+      Local f m     -> do
+        m' <- interpretDi <$> runT m
+        raise $ P.local @(DiR level msg) (fmap f) m'
+      Reset m       -> do
+        m' <- interpretDi <$> runT m
+        raise $ P.local @(DiR level msg) (\(odi, _) -> (odi, odi)) m'
+
 dup :: a -> (a, a)
 dup a = (a, a)
 
+runDiToIOFinal
+  :: forall r level msg a.
+  Members '[Final IO, Embed IO] r
+  => (DC.Log level Df1.Path msg -> IO ())
+  -> Sem (Di level Df1.Path msg ': r) a
+  -> Sem r a
+runDiToIOFinal commit m = do
+  diIn <- embedFinal newEmptyMVar
+  diOut <- embedFinal newEmptyMVar
+  void . asyncToIOFinal . async . embedFinal $ DC.new commit $ outer diIn diOut
+  inner diIn diOut
+  where
+    outer :: MVar (DC.Di level Df1.Path msg) -> MVar (DC.Di level Df1.Path msg) -> (DC.Di level Df1.Path msg) -> IO ()
+    outer aIn aOut a = do
+      putMVar aIn a
+      void $ takeMVar aOut
+
+    inner :: MVar (DC.Di level Df1.Path msg) -> MVar (DC.Di level Df1.Path msg) -> Sem r a
+    inner diIn diOut = resourceToIOFinal $ bracket
+                       (embedFinal $ takeMVar diIn)
+                       (embedFinal . putMVar diOut)
+                       (\di -> raise . P.runReader (di, di) $ interpretDi (raiseUnder $ m))
+
+runDiToStderrIOFinal :: Members '[Final IO, Embed IO] r => Sem (Di Df1.Level Df1.Path Df1.Message ': r) a -> Sem r a
+runDiToStderrIOFinal m = do
+  commit <- embedFinal @IO $ DH.stderr Df1.df1
+  runDiToIOFinal commit m
+
 runDiToIO
   :: forall r level msg a.
   Member (Embed IO) r
   => (DC.Log level Df1.Path msg -> IO ())
   -> Sem (Di level Df1.Path msg ': r) a
   -> Sem r a
-runDiToIO commit m = diToIO $ runDiIOInner commit (flip (P.runReader . dup) $ go (raiseUnder m))
-  where
-    go :: Member (Embed IO) r0
-      => Sem (Di level Df1.Path msg ': r0) a0
-      -> Sem (P.Reader (DiR level msg) ': r0) a0
-    go = reinterpretH $ \case
-      Log level msg -> do
-        (_, di) <- P.ask @(DiR level msg)
-        (embed @IO $ DC.log di level msg) >>= pureT
-      Flush         -> do
-        (_, di) <- P.ask @(DiR level msg)
-        (embed @IO $ DC.flush di) >>= pureT
-      Local f m     -> do
-        m' <- go <$> runT m
-        raise $ subsume $ P.local @(DiR level msg) (fmap f) m'
-      Reset m       -> do
-        m' <- go <$> runT m
-        raise $ subsume $ P.local @(DiR level msg) (\(odi, _) -> (odi, odi)) m'
+runDiToIO commit m = diToIO inner
+  where inner :: Sem (DiIOInner ': r) a
+        inner = runDiIOInner commit (raise . flip (P.runReader . dup) (interpretDi $ raiseUnder m))
+
 
 runDiToStderrIO :: Member (Embed IO) r => Sem (Di Df1.Level Df1.Path Df1.Message ': r) a -> Sem r a
 runDiToStderrIO m = do
