diff --git a/ChangeLog.md b/ChangeLog.md
--- a/ChangeLog.md
+++ b/ChangeLog.md
@@ -1,5 +1,16 @@
 # ChangeLog for auto-update
 
+## 0.2.7
+
+* Use `atomicModifyIORef` in `mkAutoUpdate(Helper)` to prevent race conditions
+  in multi-threaded situations.
+  [#1103](https://github.com/yesodweb/wai/pull/1103)
+
+## 0.2.6.1
+
+* Fixed documentation of when `leadingMuteEdge` and `trailingDelayEdge` were
+  introduced in `Control.Debounce`.
+
 ## 0.2.6
 
 * Using the thread version of AutoUpdate for non-threaded RTS.
diff --git a/Control/AutoUpdate/Event.hs b/Control/AutoUpdate/Event.hs
--- a/Control/AutoUpdate/Event.hs
+++ b/Control/AutoUpdate/Event.hs
@@ -65,7 +65,7 @@
 --------------------------------------------------------------------------------
 
 -- $setup
--- >>> :set -XNumericUnderscores
+-- >>> :seti -XNumericUnderscores
 -- >>> import Control.Concurrent
 
 -- |
diff --git a/Control/AutoUpdate/Thread.hs b/Control/AutoUpdate/Thread.hs
--- a/Control/AutoUpdate/Thread.hs
+++ b/Control/AutoUpdate/Thread.hs
@@ -20,7 +20,7 @@
     try,
  )
 import Control.Monad (void)
-import Data.IORef (newIORef, readIORef, writeIORef)
+import Data.IORef (newIORef, readIORef, writeIORef, atomicWriteIORef)
 import Data.Maybe (fromMaybe)
 import GHC.Conc.Sync (labelThread)
 
@@ -97,7 +97,7 @@
                 a <- catchSome $ fromMaybe (updateAction us) (updateActionModify <*> maybea)
 
                 -- we got a new value, update currRef and lastValue
-                writeIORef currRef $ Right a
+                atomicWriteIORef currRef $ Right a
                 putMVar responseVar a
 
                 -- delay until we're needed again
@@ -108,7 +108,7 @@
                 -- variable. Then loop again with the updated response
                 -- variable.
                 responseVar' <- newEmptyMVar
-                writeIORef currRef $ Left responseVar'
+                atomicWriteIORef currRef $ Left responseVar'
                 loop responseVar' (Just a)
 
         -- Kick off the loop, with the initial responseVar0 variable.
diff --git a/Control/Debounce/Internal.hs b/Control/Debounce/Internal.hs
--- a/Control/Debounce/Internal.hs
+++ b/Control/Debounce/Internal.hs
@@ -116,7 +116,7 @@
 -- >  .......    .......
 -- > X          X
 --
--- @since 0.1.6
+-- @since 0.2.3
 leadingMuteEdge :: DebounceEdge
 leadingMuteEdge = LeadingMute
 
@@ -158,7 +158,7 @@
 --         X                   X
 -- @
 --
--- @since 0.1.6
+-- @since 0.2.3
 trailingDelayEdge :: DebounceEdge
 trailingDelayEdge = TrailingDelay
 
@@ -242,16 +242,16 @@
                     ignoreExc action
                     -- 5)
                     putMVar baton ()
-        -- TRAILING DELAY
-        --
-        --   1) get current time -> /now/
-        --   2) try take baton to start
-        --   3) success -> set time var to /now/ & start worker, failed -> update time var to /now/
-        --   4) worker waits minimum delay
-        --   5) check diff of time var with /now/
-        --   6) less -> wait the difference, same/more -> do action
-        --   7) after action, recheck if there was any trigger
-        --   8) put baton back
+    -- TRAILING DELAY
+    --
+    --   1) get current time -> /now/
+    --   2) try take baton to start
+    --   3) success -> set time var to /now/ & start worker, failed -> update time var to /now/
+    --   4) worker waits minimum delay
+    --   5) check diff of time var with /now/
+    --   6) less -> wait the difference, same/more -> do action
+    --   7) after action, recheck if there was any trigger
+    --   8) put baton back
     trailingDelayDebounce timeTVar = do
         -- 1)
         now <- getMonotonicTimeNSec
diff --git a/auto-update.cabal b/auto-update.cabal
--- a/auto-update.cabal
+++ b/auto-update.cabal
@@ -1,5 +1,5 @@
 name:                auto-update
-version:             0.2.6
+version:             0.2.7
 synopsis:            Efficiently run periodic, on-demand actions
 description:         API docs and the README are available at <http://www.stackage.org/package/auto-update>.
 homepage:            https://github.com/yesodweb/wai
diff --git a/test/Control/DebounceSpec.hs b/test/Control/DebounceSpec.hs
--- a/test/Control/DebounceSpec.hs
+++ b/test/Control/DebounceSpec.hs
@@ -1,33 +1,34 @@
 {-# LANGUAGE NumericUnderscores #-}
+
 module Control.DebounceSpec (main, spec) where
 
 import Control.Concurrent (
     MVar,
     newEmptyMVar,
-    takeMVar,
-    putMVar,
     newMVar,
+    putMVar,
+    takeMVar,
     threadDelay,
     tryReadMVar,
  )
 import Control.Debounce (
-    DebounceSettings(..),
+    DebounceSettings (..),
+    defaultDebounceSettings,
     leadingEdge,
     leadingMuteEdge,
-    trailingEdge,
     trailingDelayEdge,
-    defaultDebounceSettings,
+    trailingEdge,
  )
 import qualified Control.Debounce.Internal as DI
 import Control.Monad (void)
 import Control.Monad.Catch
-import Control.Retry (recovering, constantDelay, limitRetries)
-import Data.IORef (IORef, readIORef, newIORef, modifyIORef)
+import Control.Retry (constantDelay, limitRetries, recovering)
+import Data.IORef (IORef, modifyIORef, newIORef, readIORef)
 import Data.Word (Word64)
 import GHC.Clock (getMonotonicTime)
-import Test.Hspec (Spec, describe, it, shouldReturn, hspec)
 import Test.HUnit (assertBool)
 import Test.HUnit.Lang (HUnitFailure (HUnitFailure))
+import Test.Hspec (Spec, describe, hspec, it, shouldReturn)
 
 spec :: Spec
 spec = describe "mkDebounce" $ do
