diff --git a/CHANGELOG.md b/CHANGELOG.md
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,5 +1,9 @@
 # lzlib
 
+## 0.3.0.5
+
+  * `bracket` things better
+
 ## 0.3.0.4
 
   * Use `bracket` and fix space leak
diff --git a/lzlib.cabal b/lzlib.cabal
--- a/lzlib.cabal
+++ b/lzlib.cabal
@@ -1,6 +1,6 @@
 cabal-version:      1.18
 name:               lzlib
-version:            0.3.0.4
+version:            0.3.0.5
 license:            BSD3
 license-file:       LICENSE
 copyright:          Copyright: (c) 2019 Vanessa McHale
diff --git a/src/Codec/Lzip.hs b/src/Codec/Lzip.hs
--- a/src/Codec/Lzip.hs
+++ b/src/Codec/Lzip.hs
@@ -55,19 +55,26 @@
 decompress :: BSL.ByteString -> BSL.ByteString
 decompress bs = unsafeDupablePerformIO $ do
 
-    decoder <- lZDecompressOpen
-    maxSz <- lZDecompressWriteSize decoder
-
     let bss = BSL.toChunks bs
         -- TODO: this might be silly: does it force everything into memory
         -- prematurely?
         sz = maximum (BS.length <$> bss)
-        bufMax = fromIntegral maxSz
 
+    let setup = do
+            decoder <- lZDecompressOpen
+            maxSz <- lZDecompressWriteSize decoder
+            let bufMax = fromIntegral maxSz
+            buf <- mallocBytes sz
+            pure (decoder, buf, bufMax)
+
+    let cleanup (decoder, buf, _) =
+            lZDecompressClose decoder *>
+            free buf
+
     res <- bracket
-        (mallocBytes sz)
-        ((lZDecompressClose decoder *>) . free)
-        (\buf -> loop decoder bss bufMax (buf, sz) mempty)
+        setup
+        cleanup
+        (\(decoder, buf, bufMax) -> loop decoder bss bufMax (buf, sz) mempty)
 
     pure (BSL.fromChunks res)
 
@@ -115,14 +122,21 @@
 
     let bss = BSL.toChunks bstr
         sz = fromIntegral (BSL.length bstr)
+        delta = sz `div` 4 + 64
 
-    encoder <- lZCompressOpen (fromIntegral $ dictionarySize sz) (fromIntegral matchLenLimit) (fromIntegral memberSize)
+    let setup = do
+            encoder <- lZCompressOpen (fromIntegral $ dictionarySize sz) (fromIntegral matchLenLimit) (fromIntegral memberSize)
+            newBytes <- mallocBytes delta
+            pure (encoder, newBytes)
 
-    let delta = sz `div` 4 + 64
-    res <-bracket
-        (mallocBytes delta)
-        ((lZCompressClose encoder *>) . free)
-        (\newBytes -> loop encoder bss (newBytes, delta) 0 mempty)
+    let cleanup (encoder, newBytes) =
+            lZCompressClose encoder *>
+            free newBytes
+
+    res <- bracket
+        setup
+        cleanup
+        (\(encoder, newBytes) -> loop encoder bss (newBytes, delta) 0 mempty)
 
     pure (BSL.fromChunks res)
 
