I built a WebTransport transport for Phoenix sockets and LiveView and put it on GitHub with a demo and a spec: GitHub - jfreeze/phoenix_web_transport: WebTransport (HTTP/3, QUIC) transport for Phoenix LiveView: one QUIC stream per component, shortest-message-first. Working prototype. · GitHub
The idea is small. A LiveView pushes every diff down one WebSocket, which is one ordered TCP stream, so a 50-byte counter update queued behind a 300 KB table diff waits for the whole table, and one lost packet stalls everything behind it. LiveView’s diff format already splits by component, so this library puts each component’s deltas on its own QUIC stream and sets the stream priority from the frame size, smallest first. The browser side is a WebSocket-shaped class handed to LiveSocket through the transport option. Nothing in Phoenix, LiveView or phoenix.js is patched; the server side is a Phoenix.Socket.Transport plus a serializer.
The QUIC listener runs beside your existing Bandit endpoint. It uses cowboy’s experimental HTTP/3 and WebTransport layer on top of emqx’s quicer (msquic), because nothing else on the BEAM speaks QUIC yet. Bandit stays in charge of HTTP and the WebSocket fallback.
Status: it works end to end in Chrome against a local server, with the two-component demo page showing lane 0 for the join, lane 1 carrying kilobytes for the small component and lane 2 carrying megabytes for the table. On unthrottled loopback both transports measure the same, which is expected since the browser’s DOM patch dominates there. I have not measured it over a real network. A cowboy PR adding a set_stream_priority WebTransport command is up at Add a set_stream_priority WebTransport command by jfreeze · Pull Request #1725 · ninenines/cowboy · GitHub, and cowboy’s own suite passes with it.
Where I think this pays off is LiveView on mobile: bursty loss, long round trips, and QUIC’s per-stream recovery and one-round-trip handshake on top of the split. It needs a direct UDP path with a public cert, so it will not work behind Cloudflare Tunnel, which is how I host, so I cannot run the test that matters myself.
Two asks. If you serve LiveView to phones and have a host you can open a UDP port on, I would like a phone-on-cellular measurement with the demo page. And if anyone is working on QUIC for Thousand Island or Bandit, I would rather build the listener on that than on cowboy.
Known gaps are listed in the README: automatic fallback to WebSocket on handshake failure, auth on connect (WebTransport sends no cookies), and a per-diff sequence number so events pushed alongside a component delta fire after it lands.


















