ALPN Explained: HTTP/2, HTTP/3, and Protocol Negotiation

ALPN decides which application protocol rides on a fresh TLS (or QUIC) connection, so it’s the quiet handshake step that picks HTTP/1.1, HTTP/2, or HTTP/3 before a single request is sent. Get ALPN right and clients take the fastest lane with fewer retries; get it wrong and they fall back, stall on UDP, or stick to HTTP/1.1 despite having a modern stack.
Most clients offer several protocol IDs during the handshake. The server selects one and the rest are ignored. For traditional TLS over TCP this decides between http/1.1
and h2
; for QUIC, the same idea happens inside the TLS 1.3 handshake carried by UDP and the token is h3
. Your job is to present sensible options, support the right ciphers, and advertise HTTP/3 only when the path can carry it.
Below we break down how ALPN works, what HTTP/2 and HTTP/3 expect from your TLS and firewall, how discovery via Alt-Svc and HTTPS DNS records influences client behavior, and a practical playbook to debug mismatches and slow fallbacks.
How ALPN Works
During the initial handshake, the client sends a list of protocol names (for example, “h3”, “h2”, “http/1.1”). The server picks one it supports and includes that choice in the handshake response. There’s no mid-connection switch; if either side dislikes the outcome, they must reconnect. On failure to negotiate, clients typically fall back to HTTP/1.1 or try a different route.
Selection Strategy
Order matters only on the client side. Servers should choose the best mutually supported option, not always the first offered. In practice, you’ll see clients offer “h3” first when they already learned about HTTP/3 support via Alt-Svc or HTTPS DNS records; otherwise they’ll offer “h2” and “http/1.1”.
Signals That Affect Choice
Clients combine ALPN with other signals: cached Alt-Svc advertisements, HTTPS DNS records that include alpn hints, and local policy such as “avoid UDP on captive portals.” That’s why the same domain can use HTTP/3 in one place and HTTP/2 in another during rollout.
HTTP/2 over TLS: What Servers and Clients Expect
HTTP/2 runs over TLS with ALPN “h2”. Servers should use TLS 1.2 or newer and disable legacy features that HTTP/2 forbids, like TLS-level compression and renegotiation. Stick to AEAD ciphers. Offer “h2” and “http/1.1” together so older clients can still connect. If you terminate at a CDN or proxy, ensure it also speaks h2 to the origin when needed or tunnels requests efficiently.
Operational Notes
Because HTTP/2 multiplexes streams on a single TCP connection, packet loss can stall multiple requests at once. Keep initial congestion window and TCP pacing sane, prefer BBR or a well-tuned CUBIC, and watch head-of-line blocking in lossy last miles.
HTTP/3 over QUIC: What Changes
HTTP/3 uses QUIC over UDP with ALPN “h3” inside a TLS 1.3 handshake carried by QUIC frames. QUIC handles encryption, reliability, and stream multiplexing in user space, which avoids TCP head-of-line blocking and allows faster migration between networks. The flipside: firewalls and middleboxes must pass UDP 443, and path MTU discovery relies on proper ICMP behavior.
Readiness Checks
Before you advertise HTTP/3, confirm that your edge, DDoS layer, and observability stack understand QUIC. Check that rate limiters, WAF rules, and NAT timeouts don’t assume TCP. Validate that UDP 443 reaches all edge locations and that you can collect per-connection metrics like handshake success and version negotiation.
Cipher Suites and TLS Versions
For HTTP/2, use TLS 1.2 or 1.3 with AEAD ciphers (AES-GCM or ChaCha20-Poly1305). Disable weak suites and avoid older protocol versions. For HTTP/3, QUIC mandates TLS 1.3 and uses the TLS 1.3 cipher suite names (for example, TLS_AES_128_GCM_SHA256 or TLS_CHACHA20_POLY1305_SHA256). Favor ChaCha20-Poly1305 for mobile-heavy regions where CPUs lack AES acceleration; otherwise AES-GCM is fine.
Discovery: Alt-Svc and HTTPS DNS Records
Clients don’t guess at HTTP/3; they learn it. The most common path is an Alt-Svc header served over HTTP/2 or HTTP/1.1 that advertises h3 with a max-age and port 443. Increasingly, HTTPS DNS records (SVCB/HTTPS) also advertise protocol hints, alpn lists, and even alternate endpoints. Both signals prime the client to offer “h3” first on the next connection.
Cache Scope and Freshness
Alt-Svc is cached per origin and can outlive a brief outage. Keep modest lifetimes during rollout and raise them after stability proves out. If you switch off HTTP/3, serve an empty Alt-Svc for a while so clients stop trying UDP.
Server and CDN Configuration Patterns
Terminate TLS with a certificate chain all clients trust, enable OCSP stapling, and publish intermediate certs correctly. Offer a clean ALPN set: “h3”, “h2”, and “http/1.1”. On proxies, ensure upstream pools match the negotiated protocol to avoid downgrades. For CDNs, enable HTTP/3 only on properties where UDP telemetry looks healthy and error budgets can absorb regional quirks during rollout.
Firewall and Network Edges
Allow UDP 443 at the perimeter, confirm symmetric paths through load balancers, and monitor packet loss and PMTUD events. Some middleboxes treat long-lived UDP as suspicious; tune timeouts so QUIC connections don’t reset mid-transfer.
Debugging Playbook
Start at the client: check which protocol was negotiated and the handshake times. If HTTP/3 fails, confirm UDP reachability to 443 and whether the client learned h3 via Alt-Svc or DNS. If HTTP/2 is missing, inspect ALPN choices in a TLS probe and verify that the server isn’t stripping “h2”.
Step-by-Step Checks
Resolve the hostname and verify A/AAAA reachability; probe TLS to list ALPN options; request a page and capture response headers to see Alt-Svc; check logs for version negotiation failures; compare success rates and latencies per protocol and per region; if UDP is blocked, validate whether fallback to HTTP/2 is fast enough.
Common Symptoms and Root Causes
HTTP/1.1 only: server didn’t offer “h2” due to TLS policy or misconfig. HTTP/3 connects then stalls: UDP 443 passed but PMTUD or a middlebox drops larger packets. Frequent fallbacks: Alt-Svc advertised too aggressively to regions where UDP is impaired. Poor mobile performance on AES-GCM: choose ChaCha20-Poly1305 for those segments.
Performance Tuning That Pays Off
Keep TLS tickets and session resumption healthy to shrink handshakes. For HTTP/3, enable 0-RTT only for idempotent routes and measure replay risk. Tune initial congestion windows to your edge bandwidth-delay product and watch queueing delay; ECN and pacing can help. On HTTP/2, right-size concurrent streams and flow-control windows to avoid thrash on high-latency paths.
Rollout Approach with Fewer Surprises
Enable HTTP/2 everywhere first with strict TLS policies, then light up HTTP/3 behind feature flags. Advertise Alt-Svc with short lifetimes, start with a subset of regions, and compare error rates and p95 handshake times between HTTP/2 and HTTP/3. Only increase coverage when dashboards show clear wins and stable UDP paths.