diff --git a/hydraw/app/Main.hs b/hydraw/app/Main.hs
index 1d0a9fd317e..ddc54540505 100644
--- a/hydraw/app/Main.hs
+++ b/hydraw/app/Main.hs
@@ -2,9 +2,10 @@ module Main where
 
 import Hydra.Prelude
 
+import Control.Monad.Class.MonadAsync (async)
 import Hydra.Cardano.Api (NetworkId (..), NetworkMagic (..))
 import Hydra.Network (Host, readHost)
-import Hydra.Painter (Pixel (..), paintPixel, withClient)
+import Hydra.Painter (Pixel (..), paintPixel, withClient, withClientNoRetry)
 import Network.HTTP.Types.Status (status200, status400, status404)
 import Network.Wai (
   Application,
@@ -23,9 +24,8 @@ main = do
   key <- requireEnv "HYDRAW_CARDANO_SIGNING_KEY"
   host <- parseHost =<< requireEnv "HYDRA_API_HOST"
   network <- parseNetwork =<< requireEnv "HYDRAW_NETWORK"
-  withClient host $ \cnx ->
-    Warp.runSettings settings $
-      Wai.websocketsOr WS.defaultConnectionOptions (websocketApp host) (httpApp network key cnx)
+  Warp.runSettings settings $
+    Wai.websocketsOr WS.defaultConnectionOptions (websocketApp host) (httpApp network key host)
  where
   port = 1337
 
@@ -66,18 +66,20 @@ websocketApp :: Host -> WS.PendingConnection -> IO ()
 websocketApp host pendingConnection = do
   frontend <- WS.acceptRequest pendingConnection
   withClient host $ \backend ->
-    concurrently_
+    race_
       (forever $ WS.receive frontend >>= WS.send backend)
       (forever $ WS.receive backend >>= WS.send frontend)
 
-httpApp :: NetworkId -> FilePath -> WS.Connection -> Application
-httpApp networkId key cnx req send =
+httpApp :: NetworkId -> FilePath -> Host -> Application
+httpApp networkId key host req send =
   case (requestMethod req, pathInfo req) of
     ("GET", "paint" : args) -> do
       case traverse (readMay . toString) args of
         Just [x, y, red, green, blue] -> do
           putStrLn $ show (x, y) <> " -> " <> show (red, green, blue)
-          paintPixel networkId key cnx Pixel{x, y, red, green, blue}
+          -- | spawn a connection in a new thread
+          void $ async $ withClientNoRetry host $ \cnx ->
+            paintPixel networkId key cnx Pixel{x, y, red, green, blue}
           send $ responseLBS status200 corsHeaders "OK"
         _ ->
           send handleError
diff --git a/hydraw/hydraw.cabal b/hydraw/hydraw.cabal
index 1d824f93f08..1eba9c167a3 100644
--- a/hydraw/hydraw.cabal
+++ b/hydraw/hydraw.cabal
@@ -72,6 +72,7 @@ executable hydraw
     , hydra-node
     , hydra-prelude
     , hydraw
+    , io-classes
     , safe
     , wai
     , wai-websockets
diff --git a/hydraw/src/Hydra/Painter.hs b/hydraw/src/Hydra/Painter.hs
index 3ddd0aae2e7..7160086f393 100644
--- a/hydraw/src/Hydra/Painter.hs
+++ b/hydraw/src/Hydra/Painter.hs
@@ -42,6 +42,12 @@ paintPixel networkId signingKeyPath cnx pixel = do
   flushQueue =
     race_ (threadDelay 0.25) (void (receive cnx) >> flushQueue)
 
+-- | Same as 'withClient' except we don't retry if connection fails.
+withClientNoRetry :: Host -> (Connection -> IO ()) -> IO ()
+withClientNoRetry Host{hostname, port} action =
+  runClient (toString hostname) (fromIntegral port) "/" action
+    `catch` \(e :: IOException) -> print e >> threadDelay 1
+
 withClient :: Host -> (Connection -> IO ()) -> IO ()
 withClient Host{hostname, port} action =
   retry