diff --git a/ChangeLog.md b/ChangeLog.md
--- a/ChangeLog.md
+++ b/ChangeLog.md
@@ -1,5 +1,10 @@
 # binary-io
 
+## 0.6.2
+
+* Revert changes from 0.6.0 in order to preserve write atomicity
+* Implement StationaryReader which powers Reader without concurrency primitives
+
 ## 0.6.1
 
 * Remove eta-reductions that cause GHC 9 builds to fail
diff --git a/binary-io.cabal b/binary-io.cabal
--- a/binary-io.cabal
+++ b/binary-io.cabal
@@ -5,7 +5,7 @@
   binary-io
 
 version:
-  0.6.1
+  0.6.2
 
 category:
   Data, Parsing, IO
diff --git a/lib/Data/Binary/IO/Lifted.hs b/lib/Data/Binary/IO/Lifted.hs
--- a/lib/Data/Binary/IO/Lifted.hs
+++ b/lib/Data/Binary/IO/Lifted.hs
@@ -45,7 +45,6 @@
 
 import Prelude hiding (read)
 
-import           Control.Arrow ((&&&))
 import qualified Control.Concurrent.Classy as Concurrent
 import           Control.Monad (join, unless)
 import qualified Control.Monad.Catch as Catch
@@ -58,8 +57,7 @@
 import qualified Data.Binary.Put as Put
 import           Data.ByteString (ByteString)
 import qualified Data.ByteString as ByteString
-import           Data.ByteString.Lazy (toChunks, toStrict)
-import           Data.Foldable (traverse_)
+import           Data.ByteString.Lazy (toStrict)
 import           Data.IORef (atomicModifyIORef', mkWeakIORef, newIORef)
 import qualified Deque.Strict as Deque
 import           System.IO (Handle, hSetBinaryMode)
@@ -103,43 +101,36 @@
 
 newStationaryReaderWith
   :: forall m
-  .  Concurrent.MonadConc m
+  .  Catch.MonadMask m
   => m ByteString
   -> m (StationaryReader m)
 newStationaryReaderWith getChunk = do
-  inputRef <- Concurrent.newIORef ByteString.empty
-
   let
-    make = StationaryReader $ \get -> do
-      input <- lift $ Concurrent.readIORef inputRef
-      loop $ Get.pushChunk (Get.runGetIncremental get) input
+    make initialInput = StationaryReader $ \get ->
+      loop initialInput $ Get.pushChunk (Get.runGetIncremental get) initialInput
 
-    loop :: Get.Decoder a -> ExceptT ReaderError m (StationaryReader m, a)
-    loop = \case
-      Get.Fail remainingBody offset errorMessage -> do
-        input <- lift $ Concurrent.readIORef inputRef
+    loop :: ByteString -> Get.Decoder a -> ExceptT ReaderError m (StationaryReader m, a)
+    loop inputForError = \case
+      Get.Fail remainingBody offset errorMessage ->
         except $ Left ReaderGetError
           { readerErrorRemaining = remainingBody
           , readerErrorOffset = offset
-          , readerErrorInput = input
+          , readerErrorInput = inputForError
           , readerErrorMessage = errorMessage
           }
 
       Get.Done remainingBody _ value -> Catch.mask_ $ do
-        lift $ Concurrent.writeIORef inputRef remainingBody
-        pure (make, value)
+        pure (make remainingBody, value)
 
       Get.Partial continue -> do
-        chunk <- lift $ Catch.mask $ \restore -> do
-          chunk <- restore getChunk
+        chunk <- lift getChunk
+        loop (inputForError <> chunk) $ continue $
           if ByteString.null chunk then
-            pure Nothing
+            Nothing
           else
-            Concurrent.atomicModifyIORef' inputRef $ (<> chunk) &&& const (Just chunk)
-
-        loop $ continue chunk
+            Just chunk
 
-  pure make
+  pure (make ByteString.empty)
 
 -- | @since 0.4.0
 newtype Reader m = Reader
@@ -242,14 +233,13 @@
 --
 -- @since 0.4.0
 newWriterWith
-  :: Applicative m
+  :: Functor m
   => (ByteString -> m ()) -- ^ Chunk writer
   -> Writer m
 newWriterWith write = Writer $ \put -> do
   let (result, body) = Put.runPutM put
-  result <$
-    -- Instead of allocating a single big
-    traverse_ write (toChunks body)
+  -- We allocate one big ByteString chunk to preserve write atomicity.
+  result <$ write (toStrict body)
 
 -- | Create a writer.
 --
diff --git a/test/Data/Binary/IOSpec.hs b/test/Data/Binary/IOSpec.hs
--- a/test/Data/Binary/IOSpec.hs
+++ b/test/Data/Binary/IOSpec.hs
@@ -10,9 +10,12 @@
 import           Data.Bifoldable (bitraverse_)
 import           Data.Binary (Binary (..), encode)
 import           Data.Binary.IO
+import           Data.Binary.Put (putByteString)
 import qualified Data.ByteString as ByteString
+import qualified Data.ByteString.Char8 as ByteString.Char8
 import qualified Data.ByteString.Lazy as ByteString.Lazy
 import           Data.Foldable (for_)
+import           Data.IORef (atomicModifyIORef', newIORef, readIORef)
 import           Data.List (isInfixOf)
 import           Data.Typeable (typeOf)
 import qualified System.IO as IO
@@ -80,7 +83,7 @@
 withPipe = Hspec.before createUnbufferedPipe
 
 spec :: Hspec.Spec
-spec = do
+spec = Hspec.parallel $ do
   Hspec.describe "Reader" $ do
     let
       testReads value =
@@ -181,6 +184,22 @@
         closeHandle handleWrite
 
         Hspec.shouldThrow (write writer "Hello World") isIllegalOperation
+
+    Hspec.it "preserves atomicity" $ do
+      chunksRef <- newIORef []
+
+      let
+        writer = newWriterWith $ \chunk -> atomicModifyIORef' chunksRef $ \chunks ->
+          (chunks ++ [chunk], ())
+
+      runPut writer $ putByteString $ ByteString.Char8.pack "Hello"
+      runPut writer $ putByteString $ ByteString.Char8.pack "World"
+      runPut writer $ do
+        putByteString $ ByteString.Char8.pack "Hello"
+        putByteString $ ByteString.Char8.pack "World"
+
+      chunks <- readIORef chunksRef
+      chunks `Hspec.shouldBe` map ByteString.Char8.pack ["Hello", "World", "HelloWorld"]
 
   Hspec.describe "Pipe" $ do
     Hspec.it "is connected" $ do
