Livery 0.2.0 is out. This is the first public release.
Livery is a native Erlang web framework, written very much in the spirit of Axum, Tower and Hyper. You write one router and one middleware stack, and it serves them over HTTP/1.1, HTTP/2 and HTTP/3 from a single runtime, sharing the same handlers across the three adapters and advertising Alt-Svc so clients can move up to H3.
Why it is shaped this way
A handler is a plain function, and a piece of middleware is a continuation over immutable values, call(Req, Next, State) -> Resp. It is the Tower/Axum model, not the old (req, res, next) where everyone mutates a shared request. Req and Resp are plain records, never a shared mutable handle, so they are easy to pass between processes and easy to test. Next is simply the rest of the pipeline, handed to you as a function, so wrapping it in a try/catch, a timeout or a span is just calling it inside your own code. The handler never has to know whether it sits on H1, H2 or H3: the request and response values are the same everywhere, and the protocol differences show up only through capabilities (trailers, extended_connect, datagrams). The nice consequence is that the very same model also runs outbound, which is exactly what the client is.
Features
-
One handler, three protocols: the same router and middleware serve H1, H2 and H3, and
Alt-Svcupgrades clients to H3. A handler never has to know which protocol it is on. -
Tower-style middleware: value-based
call(Req, Next, State) -> Resp, composable globally or per route. -
Routing and composition: a radix-trie router with path params, plus
livery_router:nest/2,3andmerge/1,2to build an area on its own and graft it in. -
Shared state:
livery:start_service/1takes a config map that every handler and middleware reads throughlivery_req:config/1,2,3. -
Streaming: chunked responses, Server-Sent Events, NDJSON, and file responses with byte ranges, over every adapter.
-
WebSocket and WebTransport: WebSocket over H1/H2/H3, WebTransport over H3.
-
Composable HTTP client (
livery_client): the outbound twin of the middleware, with timeout, retry, concurrency-limit and circuit-breaker layers, streamed bodies, and load balancing across a pool of endpoints (power-of-two-choices or round-robin, with passive outlier ejection). -
OpenAPI 3.1: generate the document from your routes, serve Redoc or Swagger UI, and validate request bodies.
-
MCP: serve the Model Context Protocol Streamable HTTP transport on the main listener.
-
Batteries included: CORS, security headers, gzip and deflate compression, multipart and form parsing, rate limiting and load shedding, ETag and conditional GET, static file serving, health and readiness endpoints, and a Prometheus
/metricshandler. -
Auth: signed session cookies, token introspection, and bearer middleware with OIDC discovery and JWKS.
-
Observability: OpenTelemetry-style traces and metrics, with trace context carried into your logs.
The dependencies moved with this release too. Livery keeps its adapters thin and protocols are handled by external libraries: quic 1.6.3, h2 0.8.0, erlang_h1 0.4.0, erlang_ws 0.3.0, webtransport 0.3.1, hackney 4.2.0 and instrument 1.1.3.
It is Apache-2.0, still early 0.x and under active development.
-
Code:
Feedback and questions are very welcome.