diff --git a/Network/Wai/Logger.hs b/Network/Wai/Logger.hs
--- a/Network/Wai/Logger.hs
+++ b/Network/Wai/Logger.hs
@@ -50,14 +50,13 @@
   , showSockAddr
   ) where
 
-import Control.Applicative ((<$>))
-import Control.Concurrent (forkIO, threadDelay, killThread)
+import Control.AutoUpdate (mkAutoUpdate, defaultUpdateSettings, updateAction)
 import Control.Exception (handle, SomeException(..), bracket)
 import Control.Monad (when, void)
 import Network.HTTP.Types (Status)
 import Network.Wai (Request)
+import System.IO (withFile, hFileSize, IOMode(..))
 import System.Log.FastLogger
-import System.EasyFile (getFileSize)
 
 import Network.Wai.Logger.Apache
 import Network.Wai.Logger.Date
@@ -69,25 +68,16 @@
 --   This 'ApacheLogger' writes log message to stdout.
 --   Each buffer (4K bytes) is flushed every second.
 withStdoutLogger :: (ApacheLogger -> IO a) -> IO a
-withStdoutLogger app = bracket setup teardown $ \(aplogger, _, _) ->
+withStdoutLogger app = bracket setup teardown $ \(aplogger, _) ->
     app aplogger
   where
     setup = do
-        (getter, updater) <- clockDateCacher
+        (getter, _updater) <- clockDateCacher
         apf <- initLogger FromFallback (LogStdout 4096) getter
         let aplogger = apacheLogger apf
-            flusher = logFlusher apf
             remover = logRemover apf
-            loop = do
-                threadDelay 1000000
-                updater
-                flusher
-                loop
-        t <- forkIO loop
-        return (aplogger, remover, t)
-    teardown (_, remover, t) = do
-        void remover
-        killThread t
+        return (aplogger, remover)
+    teardown (_, remover) = void remover
 
 ----------------------------------------------------------------
 
@@ -96,12 +86,6 @@
 
 data ApacheLoggerActions = ApacheLoggerActions {
     apacheLogger :: ApacheLogger
-    -- | Flushing log messages in the buffers.
-    --   This is explicitly called from your program.
-    --   Probably, one second and 10 seconds is proper to stdout and
-    --   log files, respectively.
-    --   See the source code of 'withStdoutLogger'.
-  , logFlusher :: IO ()
     -- | Rotating log files.
     --   This is explicitly called from your program.
     --   Probably, 10 seconds is proper.
@@ -136,13 +120,11 @@
 noLoggerInit :: IO ApacheLoggerActions
 noLoggerInit = return ApacheLoggerActions {
     apacheLogger = noLogger
-  , logFlusher = noFlusher
   , logRotator = noRotator
   , logRemover = noRemover
   }
   where
     noLogger _ _ _ = return ()
-    noFlusher = return ()
     noRotator = return ()
     noRemover = return ()
 
@@ -151,12 +133,10 @@
 stdoutLoggerInit ipsrc size dateget = do
     lgrset <- newStdoutLoggerSet size
     let logger = apache (pushLogStr lgrset) ipsrc dateget
-        flusher = flushLogStr lgrset
         noRotator = return ()
         remover = rmLoggerSet lgrset
     return ApacheLoggerActions {
         apacheLogger = logger
-      , logFlusher = flusher
       , logRotator = noRotator
       , logRemover = remover
       }
@@ -166,12 +146,10 @@
 fileLoggerInit ipsrc spec size dateget = do
     lgrset <- newFileLoggerSet size $ log_file spec
     let logger = apache (pushLogStr lgrset) ipsrc dateget
-        flusher = flushLogStr lgrset
-        rotator = logRotater lgrset spec
+        rotator = logFileRotator lgrset spec
         remover = rmLoggerSet lgrset
     return ApacheLoggerActions {
         apacheLogger = logger
-      , logFlusher = flusher
       , logRotator = rotator
       , logRemover = remover
       }
@@ -179,13 +157,14 @@
 callbackLoggerInit :: IPAddrSource -> (LogStr -> IO ()) -> IO () -> DateCacheGetter
                    -> IO ApacheLoggerActions
 callbackLoggerInit ipsrc cb flush dateget = do
-    let logger = apache cb ipsrc dateget
-        flusher = flush
+    flush' <- mkAutoUpdate defaultUpdateSettings
+        { updateAction = flush
+        }
+    let logger a b c = apache cb ipsrc dateget a b c >> flush'
         noRotator = return ()
         remover = return ()
     return ApacheLoggerActions {
         apacheLogger = logger
-      , logFlusher = flusher
       , logRotator = noRotator
       , logRemover = remover
       }
@@ -199,8 +178,8 @@
 
 ----------------------------------------------------------------
 
-logRotater :: LoggerSet -> FileLogSpec -> IO ()
-logRotater lgrset spec = do
+logFileRotator :: LoggerSet -> FileLogSpec -> IO ()
+logFileRotator lgrset spec = do
     over <- isOver
     when over $ do
         rotate spec
@@ -208,9 +187,7 @@
   where
     file = log_file spec
     isOver = handle (\(SomeException _) -> return False) $ do
-        -- The log file is locked by GHC.
-        -- We need to get its file size by the way not using locks.
-        siz <- fromIntegral <$> getFileSize file
+        siz <- withFile file ReadMode hFileSize
         return (siz > log_file_size spec)
 
 ----------------------------------------------------------------
diff --git a/Network/Wai/Logger/Date.hs b/Network/Wai/Logger/Date.hs
--- a/Network/Wai/Logger/Date.hs
+++ b/Network/Wai/Logger/Date.hs
@@ -15,9 +15,8 @@
   , clockDateCacher
   ) where
 
-import Control.Applicative ((<$>))
+import Control.AutoUpdate (mkAutoUpdate, defaultUpdateSettings, updateAction)
 import Data.ByteString (ByteString)
-import Data.IORef (newIORef, readIORef, writeIORef)
 #if WINDOWS
 import qualified Data.ByteString.Char8 as BS
 import Data.Time
@@ -69,30 +68,17 @@
 
 ----------------------------------------------------------------
 
-data DateCache t = DateCache {
-    timeKey :: !t
-  , formattedDate :: !ByteString
-  } deriving (Eq, Show)
-
-----------------------------------------------------------------
-
-newDate :: DateCacheConf t -> t -> IO (DateCache t)
-newDate setting tm = DateCache tm <$> formatDate setting tm
-
 -- |
 -- Returning 'DateCacheGetter' and 'DateCacheUpdater'.
+--
+-- Note: Since version 2.1.2, this function uses the auto-update package
+-- internally, and therefore the @DateCacheUpdater@ value returned need
+-- not be called. To wit, the return value is in fact an empty action.
 
 clockDateCacher :: IO (DateCacheGetter, DateCacheUpdater)
 clockDateCacher = do
-    ref <- getTime zonedDateCacheConf >>= newDate zonedDateCacheConf >>= newIORef
-    return (getter ref, clock ref)
-  where
-    getter ref = formattedDate <$> readIORef ref
-    clock ref = do
-        tm <- getTime zonedDateCacheConf
-        date <- formatDate zonedDateCacheConf tm
-        let new = DateCache {
-                timeKey = tm
-              , formattedDate = date
-              }
-        writeIORef ref new
+    getter <- mkAutoUpdate defaultUpdateSettings
+        { updateAction = getTime zonedDateCacheConf
+                     >>= formatDate zonedDateCacheConf
+        }
+    return (getter, return ())
diff --git a/wai-logger.cabal b/wai-logger.cabal
--- a/wai-logger.cabal
+++ b/wai-logger.cabal
@@ -1,5 +1,5 @@
 Name:                   wai-logger
-Version:                2.1.2
+Version:                2.2.0
 Author:                 Kazu Yamamoto <kazu@iij.ad.jp>
 Maintainer:             Kazu Yamamoto <kazu@iij.ad.jp>
 License:                BSD3
@@ -18,12 +18,12 @@
                         Network.Wai.Logger.Date
                         Network.Wai.Logger.IP
   Build-Depends:        base >= 4 && < 5
+                      , auto-update
                       , blaze-builder
                       , byteorder
                       , bytestring
                       , case-insensitive
-                      , easy-file >= 0.2
-                      , fast-logger >= 2.1.4
+                      , fast-logger >= 2.2
                       , http-types
                       , network
                       , wai >= 2.0.0
@@ -43,7 +43,6 @@
   Main-Is:              doctests.hs
   Build-Depends:        base
                       , doctest
-                      , wai-test
 
 Source-Repository head
   Type:                 git
