Http-tower-hs — A Rust Tower-inspired middleware library for Haskell
Haskell Community [Unofficial]
April 6, 2026
something like this @LaurentRDC ?
import Servant.Tower.Adapter
import Tower.Middleware.Retry
import Tower.Middleware.Timeout
import Tower.Middleware.CircuitBreaker
breaker <- newCircuitBreaker
let config = CircuitBreakerConfig { cbFailureThreshold = 5, cbCooldownPeriod = 30 }
env = withTowerMiddleware
( withRetry (exponentialBackoff 3 0.5 2.0)
. withTimeout 5000
. withCircuitBreaker config breaker
) (mkClientEnv manager baseUrl)
result <- runClientM (getUsers <|> getHealth) env
working on it. Trying to see if it makes sense. I use an adapter approach now. Where http-tower-hs holds the main implementation and servant-tower-hs is just a clean and simple adapter. The question begs, will this work for other libraries as well? is it generic enough? with the current change I’m also able to do generic implementation like this (which sort of answers my question):
import Tower
-- Wrap a database query as a Service
let dbService :: Service SQL.Query [SQL.Row]
dbService = Service $ \query -> do
result <- try $ SQL.query conn query
pure $ case result of
Left err -> Left (TransportError err)
Right rows -> Right rows
-- Add resilience with the same middleware you'd use for HTTP
breaker <- newCircuitBreaker
let config = CircuitBreakerConfig { cbFailureThreshold = 5, cbCooldownPeriod = 30 }
robust = withRetry (exponentialBackoff 3 0.5 2.0)
. withTimeout 5000
. withCircuitBreaker config breaker
$ dbService
result <- runService robust "SELECT * FROM users"
which sort of should give the “aha” towards whether this is tied into http directly. The answer is no.
EDIT: working on it now. Making it a mono repo and trying to make as much of the middlewares as generic if possible.
Discussion in the ATmosphere