diff --git a/Data/TMap.hs b/Data/TMap.hs
--- a/Data/TMap.hs
+++ b/Data/TMap.hs
@@ -81,18 +81,19 @@
 -- the caching policy, e.g.,
 --
 -- @
---   import Data.TMap.Backend.StdoutBackend( newStdoutBackend )
+--   import Data.TMap.Backend.Binary( BinaryBackend,mkBinaryBackend )
 --   import Data.TMap.CacheStructure.LRU
 -- @
 --
--- will simply log all backend operations to Stdout and use a \"least recently
--- used\" cache algorithm.
+-- will use a binary-serialization backend for persistent storage and a \"least recently
+-- used\" caching algorithm.
 --
 -- Now, to create an unbounded map that uses the 'FM Int String' (see package EdisonCore) 
 -- as the map type, you can write
 --
 -- @
---   tmap = newTMapIO newStdoutBackend Nothing :: IO (TMap (FM Int) Int String StdoutBackend LRU)
+--   backend <- mkBinaryBackend \"myworkdir\" \"mytempdir\"
+--   tmap <- newTMapIO backend Nothing :: IO (TMap (FM Int) Int String BinaryBackend LRU)
 -- @
 newTMapIO :: (M.FiniteMapX map k, Ord k, B.Backend k a b,C.CacheStructure c k) 
           => b k a            -- ^ the backend
@@ -254,7 +255,7 @@
 
 -- | Sends a /B.flush/ request to the backend. Useful for asynchronous backend
 -- implementations.
-flushBackend :: (M.FiniteMapX map k, MonadIO m, Ord k, B.Backend k a b, C.CacheStructure c k) 
-             => TMap map k a b c -> m ()
+flushBackend :: (M.FiniteMapX map k, Ord k, B.Backend k a b, C.CacheStructure c k) 
+             => TMap map k a b c -> IO ()
 flushBackend tmap = B.flush (backend tmap)
 
diff --git a/Data/TMap/Backend.hs b/Data/TMap/Backend.hs
--- a/Data/TMap/Backend.hs
+++ b/Data/TMap/Backend.hs
@@ -8,39 +8,48 @@
 -- Stability   :  experimental
 -- Portability :  non-portable (requires STM)
 --
--- Provides a type class for backend instantiations. To avoid data
--- inconsistencies, these functions should not be used directly but only by 
+-- Provides a type class for backends. To avoid data
+-- inconsistencies, these functmns should not be used directly but only by 
 -- means of the TMap interface.
 --
 -----------------------------------------------------------------------------
 
 module Data.TMap.Backend( Backend(..) )
 where
-import Control.Monad.Trans( MonadIO )
+import Prelude hiding(lookup)
 
 -- | This class needs to be instantiated when developing a new
 -- backend. The backend is expected to be able to handle concurrent
 -- (non-conflicting) requests.
-class Backend k a b | a -> k where
+class Ord k => Backend k a b | a -> k where
 
     -- | Called when a new element was inserted.
-    insert     :: MonadIO m => b k a -> k -> a -> m ()
+    insert     :: b k a -> k -> a -> IO ()
 
     -- | Called when an element was updated.
-    adjust     :: MonadIO m => b k a-> (a -> a) -> k -> m ()
+    adjust     :: b k a-> (a -> a) -> k -> IO ()
     
     -- | Called when an element was deleted from the map.
-    delete     :: MonadIO m => b k a-> k -> m ()
+    delete     :: b k a-> k -> IO ()
     
     -- | Called when an element is not found in the map. 
-    lookup     :: MonadIO m => b k a -> k -> m (Maybe a)
+    lookup     :: b k a -> k -> IO (Maybe a)
 
     -- | Called by /flushBackend/ and /purgeTMap/.
-    flush      :: MonadIO m => b k a -> m ()
+    flush      :: b k a -> IO ()
 
     -- | Called in 'newTMapIO' 
-    initialize :: MonadIO m => b k a -> m ()
+    initialize :: b k a -> IO ()
 
     flush      _ = return ()
     initialize _ = return ()
 
+{-
+instance Backend k a b IO where
+  insert b k a = liftIO (insert b k a)
+  adjust b f k = liftIO (adjust b f k)
+  delete b k   = liftIO (delete b k)
+  lookup b k   = liftIO (lookup b k)
+  flush        = liftIO . flush
+  initialize   = liftIO . initialize
+-}
diff --git a/Data/TMap/Backend/Binary.hs b/Data/TMap/Backend/Binary.hs
new file mode 100644
--- /dev/null
+++ b/Data/TMap/Backend/Binary.hs
@@ -0,0 +1,99 @@
+-----------------------------------------------------------------------------
+-- |
+-- Module      :  Data.TMap.Backend.Binary
+-- Copyright   :  Peter Robinson 2009
+-- License     :  LGPL
+--
+-- Maintainer  :  Peter Robinson <thaldyron@gmail.com>
+-- Stability   :  experimental
+-- Portability :  non-portable (requires STM)
+--
+-- Proivides a (simplistic) backend using the binary package.
+-- Every entry of the map is written to a separate file where the filename
+-- is the key. 
+--
+-- Note: This interface is only thread-safe when being used via TMap!
+--
+-----------------------------------------------------------------------------
+module Data.TMap.Backend.Binary( mkBinaryBackend, BinaryBackend)
+where
+import Data.TMap.Backend
+import Data.TMap.Exception
+import Control.Concurrent.AdvSTM
+import Control.Concurrent.AdvSTM.TVar
+import Control.Concurrent.AdvSTM.TMVar 
+
+import Data.Binary
+import Control.Monad(when)
+import Control.Exception
+import System.FilePath
+import System.Directory
+import Prelude hiding(lookup,catch)
+
+-- | The binary-backend type
+data BinaryBackend k a = BinaryBackend
+  { workingDir :: FilePath 
+  , tempDir    :: FilePath
+  , entryLock :: TVar (k -> TMVar ())
+  }
+
+-- | Creates a new backend that stores one file per entry in the given working directory.
+mkBinaryBackend :: FilePath  
+                -> IO (BinaryBackend k a)
+mkBinaryBackend wd = do 
+  ex  <- doesDirectoryExist wd
+  tmp <- getTemporaryDirectory 
+  when (not ex) $ throw (BackendException "mkBinaryBackend: Working directory does not exist.")
+  when (wd==tmp) $ throw (BackendException 
+    "mkBinaryBackend: Cannot use the temporary directory as working directory.")
+  l <- newTMVarIO ()
+  eLock <- newTVarIO (\_ -> l)
+  return (BinaryBackend wd tmp eLock)
+
+
+withLockOnEntry :: BinaryBackend k a -> k -> IO c -> IO c
+withLockOnEntry b k m = do 
+  eLocks <- atomically $ do 
+    eLocks <- readTVar (entryLock b)
+    takeTMVar (eLocks k)
+    return eLocks
+  res <- m
+  atomically $ putTMVar (eLocks k) ()
+  return res
+
+--------------------------------------------------------------------------------
+
+instance (Show k,Ord k,Binary a) => Backend k a BinaryBackend where
+
+  insert b k a = do 
+    let fp = workingDir b </> (show k)
+    ex <- doesFileExist fp
+    when ex $ throw $ BackendException "insert: Entry already exists!"
+    l <- newTMVarIO ()
+    atomically $ do 
+      eLock <- readTVar (entryLock b)
+      writeTVar (entryLock b) (\k' -> if k'==k then l
+                                               else eLock k')
+    withLockOnEntry b k $ encodeFile fp a
+    
+  lookup b k = do 
+    let fp = workingDir b </> (show k)
+    ex <- doesFileExist fp
+    if not ex
+      then return Nothing
+      else do
+        res <- withLockOnEntry b k $ decodeFile fp
+        return (Just $! res) 
+
+  delete b k = do 
+    withLockOnEntry b k $ removeFile (workingDir b </> (show k))
+
+  adjust b f k = do
+    let fp  = workingDir b </> (show k)
+    let tmp = tempDir b </> (show k)
+    ex <- doesFileExist fp
+    when (not ex) $ throw (BackendException "adjust: Did not find entry in backend.")
+    withLockOnEntry b k $ do 
+      a <- (decodeFile fp :: IO a)
+      encodeFile tmp (f a)
+    renameFile tmp fp
diff --git a/Data/TMap/Backend/NoBackend.hs b/Data/TMap/Backend/NoBackend.hs
--- a/Data/TMap/Backend/NoBackend.hs
+++ b/Data/TMap/Backend/NoBackend.hs
@@ -18,7 +18,7 @@
 
 data NoBackend k a = NoBackend
 
-instance Backend k a NoBackend where
+instance (Ord k) => Backend k a NoBackend where
   insert _ _ _ = return ()
   adjust _ _ _ = return ()
   lookup _ _   = return Nothing
diff --git a/Data/TMap/Backend/StdoutBackend.hs b/Data/TMap/Backend/StdoutBackend.hs
--- a/Data/TMap/Backend/StdoutBackend.hs
+++ b/Data/TMap/Backend/StdoutBackend.hs
@@ -20,7 +20,7 @@
 
 data StdoutBackend k a = StdoutBackend
 
-instance (Show a,Show k) => Backend k a StdoutBackend where
+instance (Show a,Show k,Ord k) => Backend k a StdoutBackend where
     insert _ _ a = liftIO (print ("inserting: ",a)) >> return ()
     adjust _ _ k = liftIO (print ("adjusting: ",k)) >> return ()
     lookup _ k   = liftIO (print ("looking up: ",k)) >> return Nothing
diff --git a/Data/TMap/Exception.hs b/Data/TMap/Exception.hs
--- a/Data/TMap/Exception.hs
+++ b/Data/TMap/Exception.hs
@@ -19,7 +19,7 @@
 
 data TMapException = DuplicateEntry 
                    | EntryNotFound 
-                   | TMapNotFound 
+--                   | TMapNotFound 
                    | TMapDefaultExc String
                    | BackendException String
                    deriving (Show,Eq,Typeable)
diff --git a/Data/TStorage.hs b/Data/TStorage.hs
--- a/Data/TStorage.hs
+++ b/Data/TStorage.hs
@@ -24,7 +24,7 @@
                       tryComplete,
                       complete,
                       remove,
-                      removeKey,
+                      removeByKey,
                       apply,
                       purgeTMap,
                       purgeTMapIO,
@@ -48,46 +48,46 @@
 
 -- | Adds a new element to the map. The key is automatically deduced by the
 -- 'HasKey' instantiation.
-add :: (M.FiniteMapX map k, MonadAdvSTM m, Ord k, B.Backend k a b, C.CacheStructure c k
+add :: (M.FiniteMapX map k, MonadAdvSTM stm, Ord k, B.Backend k a b, C.CacheStructure c k
        , HasKey a k) 
-    => a -> TMap map k a b c -> m () 
+    => a -> TMap map k a b c -> stm () 
 add a = insert (key a) a
 
 
 -- | Tries to fill a partially initialized value with data from the TMap. Returns
 -- 'Nothing' if the TMap does not contain a corresponding entry. 
-tryComplete :: (M.FiniteMapX map k, MonadAdvSTM m, Ord k, B.Backend k a b, C.CacheStructure c k
+tryComplete :: (M.FiniteMapX map k, MonadAdvSTM stm, Ord k,B.Backend k a b, C.CacheStructure c k
                , HasKey a k) 
-            => a -> TMap map k a b c -> m (Maybe a)
+            => a -> TMap map k a b c -> stm (Maybe a)
 tryComplete a = lookup (key a)
 
 -- | Fills a partially initialized value with data from the TMap. Throws
--- a 'TMapNotFound' exception if there is no corresponding entry.
-complete :: (M.FiniteMapX map k, MonadAdvSTM m, Ord k, B.Backend k a b, C.CacheStructure c k
+-- an 'EntryNotFound' exception if there is no corresponding entry.
+complete :: (M.FiniteMapX map k, MonadAdvSTM stm, Ord k, B.Backend k a b, C.CacheStructure c k
             , HasKey a k) 
-         => a -> TMap map k a b c -> m a
+         => a -> TMap map k a b c -> stm a
 complete a tmap = do
   mval <- tryComplete a tmap
   case mval of
     Just val -> return val
-    Nothing  -> throw TMapNotFound
+    Nothing  -> throw EntryNotFound
 
 -- | Removes the element from the map.
-remove :: (M.FiniteMapX map k, MonadAdvSTM m, Ord k, B.Backend k a b, C.CacheStructure c k
+remove :: (M.FiniteMapX map k, MonadAdvSTM stm, Ord k, B.Backend k a b, C.CacheStructure c k
           , HasKey a k) 
-       => a -> TMap map k a b c -> m ()
+       => a -> TMap map k a b c -> stm ()
 remove a = delete (key a) 
 
 -- | Removes the entry that has the supplied key.
-removeKey :: (M.FiniteMapX map k, MonadAdvSTM m, Ord k, B.Backend k a b, C.CacheStructure c k
+removeByKey :: (M.FiniteMapX map k, MonadAdvSTM stm, Ord k, B.Backend k a b, C.CacheStructure c k
              , HasKey a k) 
-          => k -> TMap map k a b c -> m ()
-removeKey = delete 
+            => k -> TMap map k a b c -> stm ()
+removeByKey = delete 
 
 -- | Applies a function to an element that might be only partially initialized.
-apply :: (M.FiniteMapX map k, MonadAdvSTM m, Ord k, B.Backend k a b, C.CacheStructure c k
+apply :: (M.FiniteMapX map k, MonadAdvSTM stm, Ord k, B.Backend k a b, C.CacheStructure c k
          , HasKey a k) 
-       => (a -> a) -> a -> TMap map k a b c -> m a
+       => (a -> a) -> a -> TMap map k a b c -> stm a
 apply f a tmap = do
   adjust f (key a) tmap
   complete a tmap
diff --git a/Sample.hs b/Sample.hs
--- a/Sample.hs
+++ b/Sample.hs
@@ -1,27 +1,41 @@
 module Sample
 where
 import Control.Monad( when )
+import Control.Exception
 import Data.TStorage
 import Data.TMap
-import Data.TMap.Backend.StdoutBackend
+import Data.TMap.Backend.Binary
 import qualified Data.CacheStructure.LRU as C
 import Control.Concurrent.AdvSTM 
 import qualified Control.Exception as Exc
 import qualified Data.Edison.Assoc.StandardMap as M
+import Data.Data
+import Data.Typeable
+import Data.Binary
 import Prelude hiding( lookup )
 
 data Sometype = Sometype { theid :: Int, name :: String }
-                deriving (Show,Eq,Ord)
+                deriving (Show,Eq,Ord,Data,Typeable)
 
+instance Binary Sometype where
+  put (Sometype a b) = put a >> put b
+  get = get >>= \a -> get >>= \b -> return (Sometype a b)
+
+
 instance HasKey Sometype Int where
   key = theid
 
+
 sample :: IO ()
 sample = Exc.handle (\(e::Exc.SomeException) -> print e) $ do
-  tmap <- newTMapIO newStdoutBackend (Just 4) 
-            :: IO (TMap (M.FM Int) Int Sometype StdoutBackend C.LRU)
-  -- First the low level TMap interface:
-  res  <- atomically $ do
+
+  -- Let's create a TMap that uses the binary-serialization backend:
+  backend <- mkBinaryBackend "/home/thaldyron/var/test" 
+  tmap <- newTMapIO backend (Just 4) 
+            :: IO (TMap (M.FM Int) Int Sometype BinaryBackend C.LRU)
+
+  -- First let's use the low level TMap interface:
+  res  <- atomically $ (do
     insert 1 (Sometype 1 "somename")  tmap
     insert 2 (Sometype 2 "somename2") tmap
     insert 3 (Sometype 3 "somename3") tmap
@@ -30,29 +44,38 @@
     insert 6 (Sometype 6 "somename6") tmap
     lookup 2 tmap
     delete 2 tmap
-    lookup 2 tmap
+    lookup 2 tmap) 
+    -- Catch duplicate-inserts exceptions:
+    `catchSTM` (\(e::TMapException) -> if e==DuplicateEntry then return Nothing
+                                                            else throw e)
   atomically $ purgeTMap tmap
-  print ("Result1: ",res) 
+  print ("Result1: ",res)  
 
   -- Let's try the high-level TStorage interface:
   res2 <- atomically $ do
     add (Sometype 7 "somename7") tmap
-    v1 <- apply (\s -> s{name="_"}) (Sometype {theid = 4}) tmap
-    v2 <- complete (Sometype {theid = 5}) tmap
+    v1 <- apply (\s -> s{name="_"}) (Sometype {theid = 1}) tmap
+    v2 <- complete (Sometype {theid = 1}) tmap
+--    return v2
     return (v1,v2)
   print ("Result2: ",res2)
 
 test :: IO ()
 test = do
-   tmap <- newTMapIO newStdoutBackend (Just 4) 
-            :: IO (TMap (M.FM Int) Int String StdoutBackend C.LRU)
+   backend <- mkBinaryBackend "/home/thaldyron/var/test2" 
+   tmap <- newTMapIO backend (Just 4) 
+            :: IO (TMap (M.FM Int) Int String BinaryBackend C.LRU)
    atomically $ do
        isMemb <- member 1 tmap
-       when (not isMemb) $ 
+       when (not isMemb) $ do
          insert 1 "john doe" tmap
-  
    atomically $ do
      v <- lookup 1 tmap
      -- ... doing something here with 'v'
-     adjust (\_ -> "jd") 1 tmap
+     case v of
+       Nothing -> return ()
+       Just v' -> do 
+         adjust (\_ -> "jd") 1 tmap
+         onCommit $ print v'
+                  
 
diff --git a/persistent-map.cabal b/persistent-map.cabal
--- a/persistent-map.cabal
+++ b/persistent-map.cabal
@@ -1,6 +1,11 @@
 Name:           persistent-map
 Synopsis:       A thread-safe interface for finite map types with optional persistency support.
 Description:
+
+    /Changes in 0.1.0:/
+    .
+    * Added the binary serialization backend.
+    .
     This library provides a thread-safe (STM) frontend for finite map types together with a
     backend interface for persistent storage. The /TMap/ data type
     is thread-safe, since all access functions run inside an STM monad . Any type 
@@ -54,23 +59,23 @@
     probably change.
 
 Author:         Peter Robinson
-Maintainer:     thaldyron@gmail.com
+Maintainer:     Peter Robinson <thaldyron@gmail.com>
 License:        LGPL
 License-file:   LICENSE
-Version:        0.0.0
-Category:       Data, Concurrency
+Version:        0.1.0
+Category:       Middleware, Concurrency
 Stability:      experimental
 Homepage:       http://darcs.monoid.at/persistent-map
 
 build-type:     Simple                        
 cabal-version: >= 1.2.3
 library
-    ghc-options:        -Wall -fno-ignore-asserts
+    ghc-options:        -Wall -fno-ignore-asserts -fno-warn-missing-fields
 
     exposed-modules:    Data.TMap
                         Data.TStorage
---                        Data.TMap.Exception
                         Data.TMap.Backend
+                        Data.TMap.Backend.Binary
                         Data.TMap.Backend.NoBackend
                         Data.TMap.Backend.StdoutBackend
                         Data.CacheStructure
@@ -83,11 +88,12 @@
                         EdisonAPI  >= 1.2.1 && < 1.3,
                         LRU >= 0.1.1 && < 0.2,
                         EdisonCore >= 1.2.1.3 && < 1.3,
---                        binary,
-                        stm-io-hooks >= 0.2.0 && < 0.3, 
+                        stm-io-hooks >= 0.3.0 && < 0.4, 
 --                        HDBC >= 2.0 && < 2.1, 
-                        mtl >= 1.1.0.2 && < 1.2
---                        MonadCatchIO-mtl
+                        mtl >= 1.1.0.2 && < 1.2,
+                        binary >= 0.5 && < 0.6,
+                        filepath >= 1.1 && < 1.2,
+                        directory >= 1.0.0.3 && < 1.1
 
     extensions:         MultiParamTypeClasses,
                         RankNTypes, 
