HTTP/2 vs HTTP/3 (QUIC) — what problem does each one actually solve?
Both promise a faster web, but they attack completely different bottlenecks — one lives in the browser's connection pool, the other lives inside TCP itself.
LEARN BY DOINGPut your intuition to work3 steps
HTTP/2 vs HTTP/3 (QUIC) — what problem does each one actually solve?
Use the lesson’s examples and explanation to check your idea.
Personal reflection. Nothing is sent to an AI service.#The bottleneck HTTP/1.1 never solved
HTTP/1.1 has a simple rule: on a given TCP connection, a client sends a request and must wait for the full response before it can send the next one (pipelining — sending several requests without waiting — technically exists in the spec, but responses still have to come back in the same order they were requested, and enough intermediary proxies handled that badly that no real browser ever turned it on). If your page needs a stylesheet, three scripts, and a dozen images, that queue-of-one becomes the bottleneck.
Browsers worked around it the only way they could at the application layer: opening 6 to 8 parallel TCP connections per origin, plus tricks like domain sharding (serving assets from img1.example.com, img2.example.com, ...) to multiply that limit further. It worked, but it was expensive — each TCP connection means its own handshake, its own TLS negotiation, its own congestion-control ramp-up, and its own chunk of server memory. You were paying transport-layer overhead to patch an application-layer queuing problem.
#HTTP/2: multiplexing on one connection
HTTP/2 (built on Google's SPDY) replaces HTTP/1.1's plain-text request/response format with a binary framing layer. Requests and responses are split into frames, each tagged with a stream ID, and interleaved on a single TCP connection. The server can start sending the response to stream 3 before it has finished sending the response to stream 1 — true multiplexing, no more one-at-a-time queue. It also adds header compression (HPACK, since request headers are extremely repetitive across a page load) and stream prioritization.
This is a real fix for the HTTP-level head-of-line blocking above. But HTTP/2 still rides on top of TCP, and that turns out to matter more than it sounds.
#The head-of-line blocking HTTP/2 could not fix
TCP guarantees one thing above all else: bytes arrive at the application in the exact order they were sent, with nothing skipped. It does this by buffering everything after a gap and refusing to hand any of it to the application until the missing segment is retransmitted and arrives. TCP has no concept of "streams" — to the OS socket, HTTP/2's multiplexed frames are just one ordered byte stream.
So when a single packet is lost anywhere on the path, every HTTP/2 stream on that connection stalls, even ones whose frames arrived intact and have nothing to do with the lost packet, because the kernel won't release any bytes behind the gap. This is transport-level head-of-line blocking, and no amount of clever HTTP-layer framing can route around it — the problem is one layer down.
#HTTP/3: move multiplexing into the transport itself
HTTP/3 keeps HTTP/2's idea (binary frames, multiplexed streams) but drops TCP entirely and runs over QUIC, a transport protocol built on UDP. QUIC re-implements reliability and ordering itself, but crucially it does so per stream rather than for the whole connection: each QUIC stream has its own delivery guarantee, so a lost packet only stalls the one stream it belonged to. Every other stream keeps flowing.
QUIC folds in two other wins that used to be separate round trips: TLS 1.3 is built directly into the QUIC handshake rather than negotiated afterward, so establishing a new secure connection typically costs a single round trip instead of the "TCP handshake, then TLS handshake" sequence HTTP/1.1 and HTTP/2 pay — and a client resuming a previous connection can send application data on the very first flight (0-RTT), at the cost of some replay-attack considerations for non-idempotent requests. QUIC connections are also identified by a connection ID rather than the classic (source IP, source port, destination IP, destination port) 4-tuple, so a phone that hops from Wi-Fi to cellular can keep the same QUIC connection alive — "connection migration" — something that's simply impossible for TCP, which drops the connection the instant that 4-tuple changes.
#Where this actually shows up in practice
Support is negotiated, not assumed: a server advertises HTTP/3 availability via an Alt-Svc response header (e.g. Alt-Svc: h3=":443"; ma=86400) or via ALPN during TLS, and a client that can't reach it over UDP — plenty of corporate firewalls and older middleboxes block or throttle UDP outright — falls back to HTTP/2 without the user noticing. Most major CDNs (Cloudflare, Fastly, Google, Akamai) support HTTP/3 today, and most modern browsers prefer it automatically when it's offered, but your origin still needs to speak HTTP/1.1 or HTTP/2 as a fallback.
#Side by side
| HTTP/1.1 | HTTP/2 | HTTP/3 | |
|---|---|---|---|
| Transport | TCP | TCP | QUIC over UDP |
| Multiplexing | No — needs parallel connections | Yes, one connection | Yes, one connection |
| Head-of-line blocking | Yes, at the application layer | Yes, at the TCP layer | No — per-stream delivery |
| Handshake cost | TCP (1 RTT) + TLS (1–2 RTT) | Same as HTTP/1.1 | QUIC + TLS 1.3 combined (~1 RTT, 0-RTT on resume) |
| Connection migration | No | No | Yes, via connection IDs |
🧠 Check your understanding
0/3 · 0/3 answered1. What specifically causes head-of-line blocking in HTTP/2 that HTTP/3 avoids?
2. Why can a QUIC connection survive a client switching from Wi-Fi to cellular, when a TCP connection cannot?
3. What does the Alt-Svc header do?