diff --git a/Data/Conduit.hs b/Data/Conduit.hs
--- a/Data/Conduit.hs
+++ b/Data/Conduit.hs
@@ -20,6 +20,7 @@
 
       -- *** Fuse with upstream results
     , fuseBoth
+    , fuseBothMaybe
     , fuseUpstream
 
       -- ** Primitives
diff --git a/Data/Conduit/Internal/Conduit.hs b/Data/Conduit/Internal/Conduit.hs
--- a/Data/Conduit/Internal/Conduit.hs
+++ b/Data/Conduit/Internal/Conduit.hs
@@ -76,6 +76,7 @@
     , zipConduitApp
     , passthroughSink
     , fuseBoth
+    , fuseBothMaybe
     , fuseUpstream
     , sequenceSources
     , sequenceSinks
@@ -1167,6 +1168,35 @@
 fuseBoth (ConduitM up) (ConduitM down) =
     ConduitM (pipeL (up Done) (withUpstream $ generalizeUpstream $ down Done) >>=)
 {-# INLINE fuseBoth #-}
+
+-- | Like 'fuseBoth', but does not force consumption of the @Producer@.
+-- In the case that the @Producer@ terminates, the result value is
+-- provided as a @Just@ value. If it does not terminate, then a
+-- @Nothing@ value is returned.
+--
+-- One thing to note here is that "termination" here only occurs if the
+-- @Producer@ actually yields a @Nothing@ value. For example, with the
+-- @Producer@ @mapM_ yield [1..5]@, if five values are requested, the
+-- @Producer@ has not yet terminated. Termination only occurs when the
+-- sixth value is awaited for and the @Producer@ signals termination.
+--
+-- Since 1.2.4
+fuseBothMaybe
+    :: Monad m
+    => ConduitM a b m r1
+    -> ConduitM b c m r2
+    -> ConduitM a c m (Maybe r1, r2)
+fuseBothMaybe (ConduitM up) (ConduitM down) =
+    ConduitM (pipeL (up Done) (go Nothing $ down Done) >>=)
+  where
+    go mup (Done r) = Done (mup, r)
+    go mup (PipeM mp) = PipeM $ liftM (go mup) mp
+    go mup (HaveOutput p c o) = HaveOutput (go mup p) c o
+    go _ (NeedInput p c) = NeedInput
+        (\i -> go Nothing (p i))
+        (\u -> go (Just u) (c ()))
+    go mup (Leftover p i) = Leftover (go mup p) i
+{-# INLINABLE fuseBothMaybe #-}
 
 -- | Same as @fuseBoth@, but ignore the return value from the downstream
 -- @Conduit@. Same caveats of forced consumption apply.
diff --git a/changelog.md b/changelog.md
--- a/changelog.md
+++ b/changelog.md
@@ -1,3 +1,7 @@
+## 1.2.4
+
+* [fuseBothMaybe](https://github.com/snoyberg/conduit/issues/199)
+
 __1.2.3__ Expose `connect` and `fuse` as synonyms for `$$` and `=$=`, respectively.
 
 __1.2.2__ Lots more stream fusion.
diff --git a/conduit.cabal b/conduit.cabal
--- a/conduit.cabal
+++ b/conduit.cabal
@@ -1,5 +1,5 @@
 Name:                conduit
-Version:             1.2.3.1
+Version:             1.2.4
 Synopsis:            Streaming data processing library.
 description:
     Hackage documentation generation is not reliable. For up to date documentation, please see: <http://www.stackage.org/package/conduit>.
diff --git a/test/main.hs b/test/main.hs
--- a/test/main.hs
+++ b/test/main.hs
@@ -942,6 +942,27 @@
                 return (x, y, z)
             res `shouldBe` (sum [1..5], ["hello"], [6..10])
 
+        it "fuseBothMaybe with no result" $ do
+            let src = mapM_ C.yield [1 :: Int ..]
+                sink = CL.isolate 5 C.=$= CL.fold (+) 0
+            (mup, down) <- C.runConduit $ C.fuseBothMaybe src sink
+            mup `shouldBe` (Nothing :: Maybe ())
+            down `shouldBe` sum [1..5]
+
+        it "fuseBothMaybe with result" $ do
+            let src = mapM_ C.yield [1 :: Int .. 5]
+                sink = CL.isolate 6 C.=$= CL.fold (+) 0
+            (mup, down) <- C.runConduit $ C.fuseBothMaybe src sink
+            mup `shouldBe` Just ()
+            down `shouldBe` sum [1..5]
+
+        it "fuseBothMaybe with almost result" $ do
+            let src = mapM_ C.yield [1 :: Int .. 5]
+                sink = CL.isolate 5 C.=$= CL.fold (+) 0
+            (mup, down) <- C.runConduit $ C.fuseBothMaybe src sink
+            mup `shouldBe` (Nothing :: Maybe ())
+            down `shouldBe` sum [1..5]
+
     describe "catching exceptions" $ do
         it "works" $ do
             let src = do
