diff --git a/LICENSE b/LICENSE
new file mode 100644
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,29 @@
+Copyright (c) 2009, IIJ Innovation Institute Inc.
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+  * Redistributions of source code must retain the above copyright
+    notice, this list of conditions and the following disclaimer.
+  * Redistributions in binary form must reproduce the above copyright
+    notice, this list of conditions and the following disclaimer in
+    the documentation and/or other materials provided with the
+    distribution.
+  * Neither the name of the copyright holders nor the names of its
+    contributors may be used to endorse or promote products derived
+    from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
diff --git a/Setup.hs b/Setup.hs
new file mode 100644
--- /dev/null
+++ b/Setup.hs
@@ -0,0 +1,2 @@
+import Distribution.Simple
+main = defaultMain
diff --git a/System/Log/FastLogger.hs b/System/Log/FastLogger.hs
new file mode 100644
--- /dev/null
+++ b/System/Log/FastLogger.hs
@@ -0,0 +1,102 @@
+{-# LANGUAGE DoAndIfThenElse, NoImplicitPrelude, RecordWildCards #-}
+
+-- | Fast logging system to copy log data directly to Handle buffer.
+
+module System.Log.FastLogger (
+  -- * Initialization
+    initHandle
+  -- * Logging
+  , LogStr(..)
+  , hPutLogStr
+  -- * Builder
+  , hPutBuilder
+  -- * File rotation
+  , module System.Log.FastLogger.File
+  ) where
+
+import Blaze.ByteString.Builder
+import qualified Data.ByteString as BS
+import Data.ByteString.Internal (ByteString(..), c2w)
+import Data.List
+import Data.Maybe
+import Foreign
+import GHC.Base
+import GHC.IO.Buffer
+import qualified GHC.IO.BufferedIO as Buffered
+import GHC.IO.Handle.Internals
+import GHC.IO.Handle.Text
+import GHC.IO.Handle.Types
+import GHC.IORef
+import GHC.Num
+import GHC.Real
+import System.IO
+import System.Log.FastLogger.File
+
+{-| Setting a proper buffering to 'Handle'.
+-}
+initHandle :: Handle -> IO ()
+initHandle hdl = hSetBuffering hdl (BlockBuffering (Just 4096))
+
+{-| A date type to contain 'String' and 'ByteString'.
+    This data is exported so that format can be defined.
+    This would be replaced with 'Builder' someday when
+    it can be written directly to 'Handle' buffer.
+-}
+data LogStr = LS !String | LB !ByteString
+
+{-| The 'hPut' function to copy a list of 'LogStr' to the buffer
+    of 'Handle' directly.
+    If 'Handle' is associated with a file, 'AppendMode' must be used.
+-}
+hPutLogStr :: Handle -> [LogStr] -> IO ()
+hPutLogStr handle bss =
+  wantWritableHandle "hPutLogStr" handle $ \h_ -> bufsWrite h_ bss
+
+bufsWrite :: Handle__-> [LogStr] -> IO ()
+bufsWrite h_@Handle__{..} bss = do
+    old_buf@Buffer{
+        bufRaw = old_raw
+      , bufR = w
+      , bufSize = size
+      } <- readIORef haByteBuffer
+    if size - w > len then do
+        withRawBuffer old_raw $ \ptr ->
+            go (ptr `plusPtr` w)  bss
+        writeIORef haByteBuffer old_buf{ bufR = w + len }
+    else do
+        old_buf' <- Buffered.flushWriteBuffer haDevice old_buf
+        writeIORef haByteBuffer old_buf'
+        bufsWrite h_ bss
+  where
+    len = foldl' (\x y -> x + getLength y) 0 bss
+    getLength (LB s) = BS.length s
+    getLength (LS s) = length s
+    go :: Ptr Word8 -> [LogStr] -> IO ()
+    go _ [] = return ()
+    go dst (LB b:bs) = do
+      dst' <- copy dst b
+      go dst' bs
+    go dst (LS s:ss) = do
+      dst' <- copy' dst s
+      go dst' ss
+
+copy :: Ptr Word8 -> ByteString -> IO (Ptr Word8)
+copy dst (PS ptr off len) = withForeignPtr ptr $ \s -> do
+    let src = s `plusPtr` off
+    memcpy dst src (fromIntegral len)
+    return (dst `plusPtr` len)
+
+copy' :: Ptr Word8 -> String -> IO (Ptr Word8)
+copy' dst [] = return dst
+copy' dst (x:xs) = do
+    poke dst (c2w x)
+    copy' (dst `plusPtr` 1) xs
+
+{-| The 'hPut' function directory to copy 'Builder' to the buffer.
+    If 'Handle' is associated with a file, 'AppendMode' must be used.
+    The current implementation is inefficient at this moment.
+    'initHandle' must be called once beforehand if this function is used.
+    This would replace 'hPutLogStr' someday.
+-}
+hPutBuilder :: Handle -> Builder -> IO ()
+hPutBuilder hdl = BS.hPut hdl . toByteString
diff --git a/System/Log/FastLogger/File.hs b/System/Log/FastLogger/File.hs
new file mode 100644
--- /dev/null
+++ b/System/Log/FastLogger/File.hs
@@ -0,0 +1,42 @@
+module System.Log.FastLogger.File where
+
+import Control.Monad
+import System.Directory
+import System.FilePath
+
+-- | The spec for logging files
+data FileLogSpec = FileLogSpec {
+    log_file :: String
+  , log_file_size :: Integer
+  , log_backup_number :: Int
+  }
+
+-- | Checking if a log file can be written.
+check :: FileLogSpec -> IO ()
+check spec = do
+    dirExist <- doesDirectoryExist dir
+    unless dirExist $ fail $ dir ++ " does not exist or is not a directory."
+    dirPerm <- getPermissions dir
+    unless (writable dirPerm) $ fail $ dir ++ " is not writable."
+    exist <- doesFileExist file
+    when exist $ do
+        perm <- getPermissions file
+        unless (writable perm) $ fail $ file ++ " is not writable."
+  where
+    file = log_file spec
+    dir = takeDirectory file
+
+-- | Rotating log files.
+rotate :: FileLogSpec -> IO ()
+rotate spec = mapM_ move srcdsts
+  where
+    path = log_file spec
+    n = log_backup_number spec
+    dsts' = reverse . ("":) . map (('.':). show) $ [0..n-1]
+    dsts = map (path++) dsts'
+    srcs = tail dsts
+    srcdsts = zip srcs dsts
+    move (src,dst) = do
+        exist <- doesFileExist src
+        when exist $ renameFile src dst
+
diff --git a/fast-logger.cabal b/fast-logger.cabal
new file mode 100644
--- /dev/null
+++ b/fast-logger.cabal
@@ -0,0 +1,21 @@
+Name:                   fast-logger
+Version:                0.0.0
+Author:                 Kazu Yamamoto <kazu@iij.ad.jp>
+Maintainer:             Kazu Yamamoto <kazu@iij.ad.jp>
+License:                BSD3
+License-File:           LICENSE
+Synopsis:               A fast logging system
+Description:            A fast logging system
+Category:               System
+Cabal-Version:          >= 1.6
+Build-Type:             Simple
+library
+  GHC-Options:          -Wall -fno-warn-unused-do-bind
+  Exposed-Modules:      System.Log.FastLogger
+                        System.Log.FastLogger.File
+  Build-Depends:        base >= 4 && < 5,
+                        filepath, directory, bytestring, blaze-builder
+Source-Repository head
+  Type:                 git
+  Location:             git://github.com/kazu-yamamoto/fast-logger.git
+
