hop 27 of 32 · 6 min
Three versions of the same protocol
HTTP has been rewritten twice for performance, and both rewrites attack the same problem: too much waiting.
HTTP/1.1
Text based, one request and response per connection at a time.
GET /index.html HTTP/1.1
Host: example.com
HTTP/1.1 200 OK
Content-Type: text/htmlKeep alive reuses the connection for several requests, avoiding a handshake each time. But they are still strictly sequential: request two waits for response one. That is head of line blocking, and a page needing 80 resources is badly served by it.
The workarounds became standard practice and were all hacks: open six connections per host, shard assets across subdomains to get more, concatenate files into bundles, inline images as data URIs. Every one of those exists to work around one protocol limitation.
HTTP/2
Binary rather than text, and multiplexed: many requests share one connection, interleaved as frames, each with a stream identifier.
one connection
stream 1: GET /index.html ─┐
stream 3: GET /style.css ├─ interleaved, concurrent
stream 5: GET /app.js ─┘Header compression matters more than it sounds. Requests repeat almost identical headers, and cookies can be large; HPACK removes that redundancy.
Server push allowed sending resources before they were asked for. It was hard to use well, usually sent things the browser already cached, and has been removed from browsers.
HTTP/2 does not remove head of line blocking entirely. It removes it at the HTTP layer and TCP remains underneath, so one lost packet stalls every stream until it is retransmitted. On a lossy connection HTTP/2 can be worse than several HTTP/1.1 connections.
HTTP/3
Replaces TCP with QUIC, which runs over UDP and implements reliability itself.
Because each stream is independent inside QUIC, a lost packet affecting one stream does not stall the others. That is the TCP level blocking finally gone.
Two further benefits:
Faster setup. TCP handshake plus TLS handshake is two round trips. QUIC combines them into one, and zero for a resumed connection.
Connection migration. A QUIC connection is identified by a connection identifier rather than by the address and port pair, so moving from WiFi to mobile does not break it. TCP cannot do this, which is why a download fails when you leave the house.
| HTTP/1.1 | HTTP/2 | HTTP/3 | |
|---|---|---|---|
| Format | text | binary | binary |
| Concurrency | one at a time | multiplexed | multiplexed |
| Head of line | HTTP and TCP | TCP only | none |
| Transport | TCP | TCP | QUIC over UDP |
| Setup | 2 round trips | 2 | 1, or 0 resumed |