diff --git a/CHANGELOG.md b/CHANGELOG.md
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,1 +1,5 @@
+- 0.2.0.0
+  - #6 Simplify interface because the race is impossible
+    to prevent unless the connection is held until
+    getNotification returns.
 - 0.1.0.0 First version
diff --git a/README.md b/README.md
--- a/README.md
+++ b/README.md
@@ -1,6 +1,6 @@
 # `postgresql-libpq-notify`
 
-![build status](https://travis-ci.org/jfischoff/postgresql-libpq-notify.svg?branch=master)
+[![build status](https://travis-ci.org/jfischoff/postgresql-libpq-notify.svg?branch=master)](http://travis-ci.org/jfischoff/postgresql-libpq-notify)
 
 `postgresql-libpq-notify` is a low level and minimal dependency PostgreSQL notification library.
 
diff --git a/postgresql-libpq-notify.cabal b/postgresql-libpq-notify.cabal
--- a/postgresql-libpq-notify.cabal
+++ b/postgresql-libpq-notify.cabal
@@ -1,5 +1,5 @@
 name: postgresql-libpq-notify
-version: 0.1.0.0
+version: 0.2.0.0
 synopsis: Minimal dependency PostgreSQL notifications library
 description: Minimal dependency PostgreSQL notifications library. Please see README.md
 homepage:            https://github.com/jfischoff/postgresql-libpq-notify#readme
@@ -18,7 +18,6 @@
   hs-source-dirs: src
   exposed-modules: Database.PostgreSQL.LibPQ.Notify
   build-depends: base < 5
-               , async
                , postgresql-libpq
                , stm
   ghc-options: -Wall
diff --git a/src/Database/PostgreSQL/LibPQ/Notify.hs b/src/Database/PostgreSQL/LibPQ/Notify.hs
--- a/src/Database/PostgreSQL/LibPQ/Notify.hs
+++ b/src/Database/PostgreSQL/LibPQ/Notify.hs
@@ -25,21 +25,13 @@
 <http://hackage.haskell.org/trac/ghc/ticket/7353>
 
 PostgreSQL notifications support using the same connection for sending and
-receiving notifications. This pattern is particularly useful in tests and
-probably not that useful otherwise.
-
-This library relies on receiving OS notifications that new data is available to
-read from the connection's socket. However both epoll_wait and kqueue do
-not return if recvfrom is able to clear the socket receive buffer
-before they verify there is data available.
+receiving notifications.
 
-This race between recvfrom and the event processing in kqueue/epoll_wait is common
-and largely unavoidable if one is using the same connection for sending and
-receiving notifications on different threads simultaneously.
+However this implementation cannot support this usage pattern.
 
-To support this pattern the library provides an advanced API which allows custom
-interrupt to be used in addition to the socket read ready notification.
-See 'getNotificationWithConfig' for more details.
+This implementation favors low latency by utilizing socket read notifications.
+However a consequence of this implementation choice is the connection used
+to wait for the notification cannot be used for anything else.
 
 -}
 
@@ -62,23 +54,13 @@
 #endif
 import           Data.Function(fix)
 import           Data.Bifunctor(first)
-import           Control.Concurrent.Async (race)
 
 -- | Options for controlling and instrumenting the behavior of 'getNotificationWithConfig'
 data Config = Config
-  { interrupt              :: Maybe (IO ())
-  -- ^ Custom interrupt
-  , interrupted            :: IO ()
-  -- ^ Event called if the 'interrupt' is set and returns
-  --   before the 'threadWaitReadSTM' action returns.
-  , threadWaitReadReturned :: IO ()
-  -- ^ Event called if 'threadWaitReadSTM' action returns before the
-  --   'interrupt' action returns.
-  , startLoop              :: IO ()
+  { startLoop              :: IO ()
   -- ^ Called each time 'getNotificationWithConfig' loops to look for another notification
   , beforeWait             :: IO ()
-  -- ^ Event called before the thread will
-  -- wait on 'threadWaitReadSTM' action or 'interrupt' returning.
+  -- ^ Event called before the thread will wait on 'threadWaitReadSTM' action.
 #if defined(mingw32_HOST_OS)
   , retryDelay             :: Int
   -- ^ How long to wait in microseconds before retrying on Windows.
@@ -88,18 +70,13 @@
 -- | Default configuration
 defaultConfig :: Config
 defaultConfig = Config
-  { interrupt              = Nothing
-  , interrupted            = pure ()
-  , threadWaitReadReturned = pure ()
-  , startLoop              = pure ()
+  { startLoop              = pure ()
   , beforeWait             = pure ()
 #if defined(mingw32_HOST_OS)
   , retryDelay             = 100000
 #endif
   }
 
-data RetryOrReturn = Retry (IO (Either () ())) | Return PQ.Notify
-
 funcName :: String
 funcName = "Hasql.Notification.getNotification"
 
@@ -121,42 +98,27 @@
 Returns a single notification.  If no notifications are
 available, 'getNotificationWithConfig' blocks until one arrives.
 Unlike 'getNotification', 'getNotificationWithConfig' takes in an
-additional 'Config' parameter which provides custom 'interrupt' and
-various event hooks for operational insight.
+additional 'Config' parameter provides event hooks for operational insight.
 
-Using a custom 'interrupt' is necessary if one would like to call
-'getNotificationWithConfig' on one thread and @NOTIFY@ on another
-thread using the same connection.
+The connection passed in cannot be used for anything else
+while waiting on the notification or this call might never return.
 
-To support this behavior one must cause 'interrupt' to return after the
-call to @NOTIFY@ checks it's result from the server.
 
-See the test file of this package for an example of how to use a custom
-'interrupt'.
-
 Note that PostgreSQL does not
 deliver notifications while a connection is inside a transaction.
 -}
 getNotificationWithConfig
   :: Config
-  -- ^
-  -> (forall a. c -> (PQ.Connection -> IO a) -> IO a)
-  -- ^ This is a way to get a connection from a 'c'.
-  --   A concrete example would be if 'c' is 'MVar PQ.Connection'
-  --   and then this function would be 'withMVar'
-  -> c
-  -- ^ A type that can used to provide a connection when
-  --   used with the former argument. Typically a concurrency
-  --   primitive like 'MVar PQ.Connection'
+  -- ^ 'Config' to instrument and configure the retry period on Windows.
+  -> PQ.Connection
+  -- ^ The connection. The connection cannot be used for anything else
+  --   while waiting on the notification or this call might never return.
   -> IO (Either IOError PQ.Notify)
-getNotificationWithConfig Config {..} withConnection conn = fmap (first setLoc) $ try $ fix $ \next -> do
-    -- We try to get the notification or register a file descriptor callback
-    -- while holding the lock. We then give up the lock to wait.
-    -- That is why code is broken up into these two sections.
+getNotificationWithConfig Config {..} c = fmap (first setLoc) $ try $ fix $ \next -> do
     startLoop
-    e <- withConnection conn $ \c -> PQ.consumeInput c >> PQ.notifies c >>= \case
+    PQ.notifies c >>= \case
       -- We found a notification just return it
-      Just x -> pure $ Return x
+      Just x -> pure x
       -- There wasn't a notification so we need to register to wait on the file handle
       Nothing -> PQ.socket c >>= \case
         -- This is an odd error
@@ -173,37 +135,24 @@
           -- with the custom interrupt event if one is provided
           let fileNotification = atomically action
 #endif
-          pure $ Retry $ maybe (pure <$> fileNotification) (fileNotification `race`) interrupt
-
-    case e of
-      Retry raceResult -> do
-        beforeWait
-        -- Wait on either threadWaitReadSTM action or the custom interrupt
-        either (const interrupted) (const threadWaitReadReturned) =<< raceResult
-        next
-      Return x -> pure x
+          beforeWait
+          fileNotification
+          _ <- PQ.consumeInput c
+          next
 
 {-|
 Returns a single notification.  If no notifications are
 available, 'getNotification' blocks until one arrives.
 
-If 'getNotification' is called and afterwards on a different thread
-@NOTIFY@ is called using the same connection, 'getNotification' can
-block even if a notification is sent.
-
-To support this behavior one must use 'getNotificationWithConfig' instead.
+The connection passed in cannot be used for anything else
+while waiting on the notification or this call might never return.
 
 Note that PostgreSQL does not
 deliver notifications while a connection is inside a transaction.
 -}
 getNotification
-  :: (forall a. c -> (PQ.Connection -> IO a) -> IO a)
-  -- ^ This is a way to get a connection from a 'c'.
-  --   A concrete example would be if 'c' is 'MVar PQ.Connection'
-  --   and then this function would be 'withMVar'
-  -> c
-  -- ^ A type that can used to provide a connection when
-  --   used with the former argument. Typically a concurrency
-  --   primitive like 'MVar PQ.Connection'
+  :: PQ.Connection
+  -- ^ The connection. The connection cannot be used for anything else
+  --   while waiting on the notification or this call might never return.
   -> IO (Either IOError PQ.Notify)
 getNotification = getNotificationWithConfig defaultConfig
diff --git a/test/Main.hs b/test/Main.hs
--- a/test/Main.hs
+++ b/test/Main.hs
@@ -38,46 +38,45 @@
 
   beforeAll theStart $ afterAll theStop $ specWith
 
-withSetup :: (PQ.Connection -> IO ()) -> IO ()
+withSetup :: ((PQ.Connection, PQ.Connection) -> IO ()) -> IO ()
 withSetup f = either throwIO pure <=< Temp.withDbCache $ \dbCache ->
   Temp.withConfig (Temp.defaultConfig <> Temp.cacheConfig dbCache) $ \db -> do
     let localhostOpts = Temp.toConnectionOptions db
     bracket (PQ.connectdb (Options.toConnectionString localhostOpts))
       PQ.finish
-      f
+      $ \c -> bracket (PQ.connectdb (Options.toConnectionString localhostOpts))
+          PQ.finish
+          $ \c1 -> f (c, c1)
 
 spec :: Spec
 spec = aroundAll withSetup $ do
   describe "getNotificationWithConfig" $ describe "returns a notification" $ do
-    it "before" $ \conn -> do
-      connVar <- newMVar conn
+    it "before" $ \(conn1, conn2) -> do
       let initialChannel = "channel"
           initialData = "hi!"
-      _ <- withMVar connVar $ \c -> do
-          _ <- PQ.exec c $ "LISTEN " <> initialChannel
-          PQ.exec c ("NOTIFY " <> initialChannel <> ", '" <> initialData <>"';")
 
-      Right PQ.Notify {..} <- getNotification withMVar connVar
+      _ <- PQ.exec conn2 $ "LISTEN " <> initialChannel
+      _ <- PQ.exec conn1 $ "NOTIFY " <> initialChannel <> ", '" <> initialData <>"';"
+
+      Right PQ.Notify {..} <- getNotification conn2
       notifyRelname `shouldBe` initialChannel
       notifyExtra `shouldBe` initialData
 
-    it "after file notifications are registered" $ \conn -> do
-      connVar <- newMVar conn
+    it "after file notifications are registered" $ \(conn1, conn2) -> do
       ender <- newEmptyMVar
       beforeWaiter <- newEmptyMVar
       let initialChannel = "channel"
           initialData = "hi!"
-      _ <- withMVar connVar $ \c -> PQ.exec c $ "LISTEN " <> initialChannel
+      _ <- PQ.exec conn2 $ "LISTEN " <> initialChannel
       _ <- forkIO $ do
              takeMVar beforeWaiter
-             _ <- withMVar connVar $ \c ->  PQ.exec c ("NOTIFY " <> initialChannel <> ", '" <> initialData <>"';")
+             _ <- PQ.exec conn1 ("NOTIFY " <> initialChannel <> ", '" <> initialData <>"';")
              putMVar ender ()
 
       let config = defaultConfig
-            { interrupt  = Just $ takeMVar ender
-            , beforeWait = putMVar beforeWaiter ()
+            { beforeWait = putMVar beforeWaiter ()
             }
 
-      Right PQ.Notify {..} <- getNotificationWithConfig config withMVar connVar
+      Right PQ.Notify {..} <- getNotificationWithConfig config conn2
       notifyRelname `shouldBe` initialChannel
       notifyExtra `shouldBe` initialData
