The fix for the one thing HTTP/2 couldn't touch: it throws out TCP and rebuilds reliable, multiplexed, encrypted transport on top of UDP.
Why Abandon TCP At All?
HTTP/2's remaining weakness is TCP itself. One lost segment stalls every multiplexed
stream (transport head-of-line blocking). You can't fix that
without changing TCP — and TCP is baked into operating-system kernels and middleboxes worldwide, so it
effectively can't be changed.
The answer: build a new transport in user space, on top of UDP.
UDP gives you bare packet delivery with no ordering guarantees — a blank canvas. That transport is
QUIC. HTTP/3 is simply "HTTP semantics mapped onto QUIC."
QUIC understands streams natively. Loss recovery is per-stream, not
per-connection. A lost packet carrying stream 1's data only blocks stream 1 — streams 3, 5, and 7 keep
being delivered to the application. The transport-layer HOL blocking is gone.
flowchart LR
L["Lost packet (stream 1)"] --> S1["Stream 1: waits for retransmit"]
L -.no effect.-> S3["Stream 3: keeps flowing ✅"]
L -.no effect.-> S5["Stream 5: keeps flowing ✅"]
This is the whole reason HTTP/3 exists. On a clean network HTTP/3 and HTTP/2 perform similarly; the gap
opens on lossy or high-latency links (mobile, congested Wi-Fi) where independent streams shine.
Encryption Is Not Optional
QUIC has TLS 1.3 built into the transport — there is no unencrypted QUIC. Where
HTTP/2-over-TLS layers TLS on top of TCP as a separate handshake, QUIC fuses the transport and
cryptographic handshakes into one. See TLS for the handshake itself.
Fused handshake = fewer round trips. Establishing a TCP+TLS connection classically
costs a TCP handshake then a TLS handshake — two sequential round-trip groups. QUIC combines
them, so a fresh connection is typically 1-RTT, and a resumed one can be
0-RTT.
0-RTT Resumption
If the client has talked to this server before, it can cache the crypto parameters and send
application data in the very first packet — no waiting for a handshake to complete.
The catch — replay risk. 0-RTT data can be captured and replayed by an attacker, so
it must only carry idempotent, safe requests (a GET, never a
POST /pay). This is the same idempotency reasoning from
HTTP 101, now with security teeth.
Connection Migration
TCP connections are glued to the 4-tuple (source IP, source port, dest IP, dest port).
Walk out of Wi-Fi onto cellular and your IP changes — the TCP connection dies and everything restarts.
QUIC identifies a connection by a Connection ID, not the IP/port. When your network
changes, the connection migrates — the same session continues on the new path with no
re-handshake and no dropped downloads. This is a genuinely new capability, not just a speed tweak.
QPACK: HPACK for an Unordered World
HPACK assumed a single ordered TCP stream. QUIC streams can arrive out of
order, so a dynamic-table design that assumed ordering would reintroduce HOL blocking (a header on
stream 5 waiting for a table update on stream 1).
QPACK redesigns header compression to tolerate reordering: it separates table updates
onto dedicated streams and lets the encoder choose how much it's willing to block, trading a little
compression for independence.
Discovery: How Clients Find HTTP/3
A browser can't just assume UDP works (some networks block it). HTTP/3 is discovered via
Alt-Svc: a server answering over HTTP/1.1 or /2 advertises an HTTP/3 endpoint, and the
client upgrades on the next visit. It also keeps a TCP fallback ready.
HTTP/2 200 OK
alt-svc: h3=":443"; ma=86400
Real-world: because UDP is sometimes throttled or blocked by middleboxes, production
deployments run HTTP/3 and keep HTTP/2 as a fallback. You rarely pick one; you offer both and
let clients negotiate.
Key Takeaways
QUIC feature
Fixes / enables
UDP + user-space transport
Deployable without kernel/middlebox changes
Per-stream loss recovery
No transport-layer HOL blocking
Built-in TLS 1.3
Always encrypted; fused handshake
0-RTT resumption
Send data on the first packet (idempotent only)
Connection IDs
Survive network changes (migration)
QPACK
Header compression that tolerates reordering
The through-line: HTTP/1.1 → /2 → /3 is one long fight against
head-of-line blocking, chased down from the application layer,
to TCP, and finally out of TCP entirely. Read that deep-dive next to see all three layers side by side.