diff --git a/CHANGELOG.md b/CHANGELOG.md
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -2,6 +2,14 @@
 Brick changelog
 ---------------
 
+0.50
+----
+
+API changes:
+ * Added `writeBChanNonBlocking`, which does a non-blocking write to a
+   `BChan` and returns whether the write succeeded. This required
+   raising the STM lower bound to 2.4.3.
+
 0.49
 ----
 
diff --git a/brick.cabal b/brick.cabal
--- a/brick.cabal
+++ b/brick.cabal
@@ -1,5 +1,5 @@
 name:                brick
-version:             0.49
+version:             0.50
 synopsis:            A declarative terminal user interface library
 description:
   Write terminal applications painlessly with 'brick'! You write an
@@ -101,7 +101,7 @@
                        config-ini,
                        vector,
                        contravariant,
-                       stm >= 2.4,
+                       stm >= 2.4.3,
                        text,
                        text-zipper >= 0.7.1,
                        template-haskell,
diff --git a/src/Brick/BChan.hs b/src/Brick/BChan.hs
--- a/src/Brick/BChan.hs
+++ b/src/Brick/BChan.hs
@@ -2,6 +2,7 @@
   ( BChan
   , newBChan
   , writeBChan
+  , writeBChanNonBlocking
   , readBChan
   , readBChan2
   )
@@ -17,21 +18,31 @@
 -- | @BChan@ is an abstract type representing a bounded FIFO channel.
 data BChan a = BChan (TBQueue a)
 
--- |Builds and returns a new instance of @BChan@.
+-- | Builds and returns a new instance of @BChan@.
 newBChan :: Int   -- ^ maximum number of elements the channel can hold
           -> IO (BChan a)
 newBChan size = atomically $ BChan <$> newTBQueue (fromIntegral size)
 
--- |Writes a value to a @BChan@; blocks if the channel is full.
+-- | Writes a value to a @BChan@; blocks if the channel is full.
 writeBChan :: BChan a -> a -> IO ()
 writeBChan (BChan q) a = atomically $ writeTBQueue q a
 
--- |Reads the next value from the @BChan@; blocks if necessary.
+-- | Attempts to write a value to a @BChan@. If the channel has room,
+-- the value is written and this returns 'True'. Otherwise this returns
+-- 'False' and returns immediately.
+writeBChanNonBlocking :: BChan a -> a -> IO Bool
+writeBChanNonBlocking (BChan q) a = atomically $ do
+    f <- isFullTBQueue q
+    if f
+       then return False
+       else writeTBQueue q a >> return True
+
+-- | Reads the next value from the @BChan@; blocks if necessary.
 readBChan :: BChan a -> IO a
 readBChan (BChan q) = atomically $ readTBQueue q
 
--- |Reads the next value from either @BChan@, prioritizing the first @BChan@;
--- blocks if necessary.
+-- | Reads the next value from either @BChan@, prioritizing the first
+-- @BChan@; blocks if necessary.
 readBChan2 :: BChan a -> BChan b -> IO (Either a b)
 readBChan2 (BChan q1) (BChan q2) = atomically $
   (Left <$> readTBQueue q1) `orElse` (Right <$> readTBQueue q2)
