diff --git a/CHANGELOG.md b/CHANGELOG.md
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,5 +1,10 @@
 # lz4
 
+## 0.1.3.0
+
+  * Add `decompressBufSz` for frames
+  * Add some sensibly placed bang patterns
+
 ## 0.1.2.0
 
   * Add `cross` flag
diff --git a/lz4-hs.cabal b/lz4-hs.cabal
--- a/lz4-hs.cabal
+++ b/lz4-hs.cabal
@@ -1,6 +1,6 @@
 cabal-version:   1.18
 name:            lz4-hs
-version:         0.1.2.0
+version:         0.1.3.0
 license:         BSD3
 license-file:    LICENSE
 copyright:       Copyright: (c) 2020 Vanessa McHale
@@ -34,6 +34,7 @@
     hs-source-dirs:   src
     other-modules:    Codec.Lz4.Foreign
     default-language: Haskell2010
+    other-extensions: BangPatterns
     include-dirs:     cbits
     install-includes:
         cbits/lz4.h cbits/lz4frame.h cbits/lz4hc.h cbits/xxhash.h
diff --git a/src/Codec/Lz4.hs b/src/Codec/Lz4.hs
--- a/src/Codec/Lz4.hs
+++ b/src/Codec/Lz4.hs
@@ -1,3 +1,5 @@
+{-# LANGUAGE BangPatterns #-}
+
 -- | The functions in this module throw exceptions on error.
 --
 -- 'decompress' and 'compress' are fully lazy, i.e. memory efficient.
@@ -10,6 +12,7 @@
                  -- * Functions for working with frames
                  , compress
                  , decompress
+                 , decompressBufSz
                  -- * Version info
                  , lZ4VersionNumber
                  , lZ4VersionString
@@ -39,15 +42,21 @@
 
 -- | Lazily decompress a frame
 decompress :: BSL.ByteString -> BSL.ByteString
-decompress bs = runST $ do
+decompress = decompressBufSz (64 * 1014)
 
+-- | @since 0.1.3.0
+decompressBufSz :: Int -- ^ Size of the output buffer
+                -> BSL.ByteString
+                -> BSL.ByteString
+decompressBufSz bufSz bs = runST $ do
+
     let bss = BSL.toChunks bs
 
     (ctx, buf) <- LazyST.unsafeIOToST $ do
         (err, preCtx) <- lZ4FCreateDecompressionContext lZ4FGetVersion
         check err
         ctx <- castForeignPtr <$> newForeignPtr lZ4FFreeCompressionContext (castPtr preCtx)
-        dstBuf <- mallocForeignPtrBytes (64 * 1024)
+        dstBuf <- mallocForeignPtrBytes bufSz
         pure (ctx, dstBuf)
 
     BSL.fromChunks <$> loop ctx buf bss
@@ -62,12 +71,12 @@
 
 
           stepChunk :: LzDecompressionCtxPtr -> ForeignPtr a -> BS.ByteString -> LazyST.ST s (Maybe BS.ByteString, BS.ByteString)
-          stepChunk ctx dst b = LazyST.unsafeIOToST $
+          stepChunk !ctx !dst b = LazyST.unsafeIOToST $
             BS.unsafeUseAsCStringLen b $ \(buf, sz) ->
                 withForeignPtr dst $ \d ->
                     alloca $ \dSzPtr ->
                         alloca $ \szPtr -> do
-                            poke dSzPtr (64 * 1024)
+                            poke dSzPtr (fromIntegral bufSz)
                             poke szPtr (fromIntegral sz)
                             res <- lZ4FDecompress ctx d dSzPtr buf szPtr nullPtr
                             check res
@@ -116,7 +125,7 @@
                 BS.packCStringLen (castPtr d, fromIntegral res)
 
           update :: LzCtxPtr -> BS.ByteString -> LazyST.ST s BS.ByteString
-          update ctx b = LazyST.unsafeIOToST $
+          update !ctx b = LazyST.unsafeIOToST $
             BS.unsafeUseAsCStringLen b $ \(buf, sz) -> do
                 let expectedSz = lZ4FCompressBound (fromIntegral sz) nullPtr
                 dst <- mallocForeignPtrBytes (fromIntegral expectedSz)
diff --git a/test/Spec.hs b/test/Spec.hs
--- a/test/Spec.hs
+++ b/test/Spec.hs
@@ -16,7 +16,7 @@
 testRoundtripFrames :: FilePath -> TestTree
 testRoundtripFrames fp = testCase ("Roundtrip " ++ fp) $ do
     contents <- BSL.readFile fp
-    let actual = decompress (compress contents)
+    let actual = decompressBufSz (32 * 1024) (compress contents)
     actual @?= contents
 
 main :: IO ()
