Notes from rolling out HTTP/3
HTTP/3 is not an upgrade of HTTP/2 so much as a second, parallel path. That distinction shapes every operational decision that follows.
It runs on UDP, and everything assumes that is blocked
The first surprise is how many networks drop UDP wholesale. Corporate firewalls, some hotel and airport networks, and a number of mobile carriers either block it or rate-limit it hard. Because of that, HTTP/3 is advertised rather than enforced: the server adds an Alt-Svc header pointing at a QUIC endpoint, and clients that cannot reach it quietly stay on TCP.
Alt-Svc: h3=":443"; ma=86400
If you forget the header, nothing breaks — you just get no QUIC traffic, which looks identical to a broken deployment from the outside.
Verify from outside, on both paths
Checking that the port is open is not enough, because a UDP listener that never answers is indistinguishable from a filtered one at the socket level. Force the protocol in the client and compare:
curl --http3-only -sI https://example.org
curl --http2 -sI https://example.org
Then do it again from a different network. A rollout that works from one provider and fails from another is the normal case, not an anomaly.
Buffers are different
QUIC keeps its own flow control and its own retransmission timers in user space. Kernel socket buffer tuning, which is the usual first instinct, does much less here. What matters more is the per-connection receive window and the number of concurrent streams the server is willing to track, both of which are set in the server configuration rather than with sysctl.
Migration is not a flag day
Because clients fall back silently, there is no moment where HTTP/3 becomes required. That is convenient, and also the reason it is easy to ship a rollout that only half works and never notice. Keep both paths exercised deliberately, and treat a drop in QUIC share as a signal rather than background noise.