Learning objective. Learn what every QUIC/HTTP-3 deployment must configure (ALPN, certificate, transport parameters, and SETTINGS), how clients discover an HTTP/3 endpoint, and the deployment-defining challenge of load-balancing a connection identified by a connection ID rather than a four-tuple.
The four things every deployment sets #
A working HTTP/3 endpoint needs four pieces of configuration, three of which this book has already covered in depth:
- ALPN. The TLS handshake must negotiate the token
h3: "the token 'h3' is used in the Application-Layer Protocol Negotiation extension" ([RFC 9114 §3.1]). Without it there is no HTTP/3 (§2.1); ALPN is mandatory, and a failure to agree is ano_application_protocolalert ([RFC 9001 §8.1], §13.4). - A TLS certificate. QUIC always runs over TLS 1.3 (Chapter 2); the server is authenticated exactly as for HTTPS ([RFC 9001 §4.4]).
- Transport parameters. The flow-control, stream-count, idle-timeout, and connection-ID limits of Chapter 7, sized to the deployment's traffic (§7.5).
- HTTP/3 SETTINGS. Sent as the first frame on the control stream ([RFC 9114 §7.2.4],
§5.1): the QPACK capacities (Chapter 6) and
SETTINGS_MAX_FIELD_SECTION_SIZE.
Discovery: how a client finds HTTP/3 #
A client cannot assume a server speaks HTTP/3. QUIC is over UDP, and the server "MAY serve HTTP/3 on any UDP port" ([RFC 9114 §3.1]). The standard discovery path is HTTP Alternative Services: a server reached over HTTP/1.1 or HTTP/2 advertises its HTTP/3 endpoint "via the Alt-Svc HTTP response header field... using the 'h3' ALPN token" ([RFC 9114 §3.1.1]):
Alt-Svc: h3=":443"
The client caches that hint and, on a later request, tries QUIC first. (An HTTPS DNS record can carry
the same hint so the client learns of HTTP/3 support before its first connection, a common CDN
optimization, though defined outside these RFCs.)
The deployment challenge: load-balancing by connection ID #
The single biggest way QUIC deployment differs from TCP is load balancing. A TCP load balancer routes by the four-tuple, which is stable for a TCP connection's life. A QUIC connection's four-tuple is not stable. The client can migrate to a new address (Chapter 10), and a rebinding NAT can change it involuntarily (§10.3). Routing by four-tuple would send a migrated client's packets to the wrong backend and break the connection.
QUIC's answer is the connection ID, whose whole purpose is that "changes in addressing at lower protocol layers do not cause packets... to be delivered to the wrong endpoint" ([RFC 9000 §5.1]). A QUIC-aware load balancer routes on the Destination Connection ID, and the server encodes routing information into the connection IDs it issues (§10.2) so the balancer can extract a backend identifier from any connection ID and forward statelessly. When the client migrates, the connection ID is unchanged, so the balancer keeps sending it to the same backend — migration and load balancing coexist. (The precise encoding is an operational concern; the community "QUIC-LB" design is one approach, defined outside these RFCs.)
The consequence for configuration is a coupling the chapters flagged: the server's connection-ID length and
encoding must match what the balancer expects, and active_connection_id_limit must be high enough that
clients always have a spare ID to migrate with (§10.2) — get either wrong and roaming clients
silently land on the wrong backend.
Server and client patterns #
Beyond the load balancer, a few patterns recur:
- Single origin. The simplest case is one server terminating QUIC directly: certificate,
h3ALPN, transport parameters, SETTINGS, done. No connection-ID encoding needed. - Edge / CDN. Terminate QUIC at the edge, close to users, to capture the 1-RTT and 0-RTT wins
(Chapter 8); advertise HTTP/3 via
Alt-Svcand theHTTPSDNS record; keep certificate chains small so the server's first flight stays under the amplification limit (§8.3). - Client pooling and fallback. A client should reuse one warm connection for many requests
(§8.3), cache
Alt-Svchints, and, crucially, fall back to HTTP/2 over TCP when UDP is blocked. Many networks throttle or block UDP/443, so a robust client races HTTP/3 against an HTTP/2 attempt and uses whichever connects, rather than failing when QUIC cannot get out.
Worked example: a request across a migration #
Trace Figure 13.1-1. The client first talks to the origin over HTTP/2 and receives Alt-Svc: h3=":443";
it caches this. Next time it opens a QUIC connection with ALPN h3, choosing a Destination Connection ID;
the load balancer reads that connection ID, extracts the encoded backend, and forwards to it. The backend
completes the handshake (certificate, transport parameters, SETTINGS as the first control-stream frame)
and requests flow. When the user walks onto a cellular network, the client's address changes but its
connection ID does not, so the same packets, from a new four-tuple, still carry a connection ID the balancer
maps to the same backend. The connection survives the migration (Chapter 10) and stays on
its backend — the two mechanisms working together.
"Terminate QUIC at the edge" hides real cost that TCP deployments don't have. Each QUIC connection is a TLS
session with per-connection crypto state and a congestion controller, and unlike a TCP load balancer that can
splice byte streams, a QUIC balancer that only routes (rather than terminates) must forward every packet to a
backend that holds the keys. That is why the connection-ID routing layer exists: it lets a cheap, stateless
balancer steer encrypted packets to the right stateful backend without terminating the connection. Getting
that layer right (CID encoding, length, and the active_connection_id_limit) is the core operational task
of an HTTP/3 deployment, and the one with no TCP equivalent.
editorial Stand up the single-origin case first and confirm end to end:
ALPN negotiates h3, SETTINGS is the first control-stream frame, and a request completes. The §5.5 lab
is exactly this. Only then add a load balancer, and treat connection-ID encoding as a first-class design
decision coordinated between server and balancer, not an afterthought (a mismatch shows up as connections that
work until the first migration, then break). Always ship the HTTP/2-over-TCP fallback: measure the fraction of
users on whom QUIC fails to connect, because on real networks it is never zero, and a client without fallback
simply looks broken to them.
Takeaways #
Every HTTP/3 deployment configures four things: h3 ALPN, a TLS certificate, transport parameters, and
first-frame SETTINGS. Clients discover HTTP/3 via Alt-Svc (and the HTTPS DNS record), falling back to
HTTP/2 over TCP where UDP is blocked. The deployment challenge with no TCP analogue is load-balancing a
connection identified by a connection ID rather than a four-tuple: a QUIC-aware balancer routes on the
Destination Connection ID, which the server encodes with routing information, so migration and load balancing
coexist. With deployments configured, §13.2 turns to the interoperability pitfalls that break two
correctly-configured stacks talking to each other.