A GET /index.html means the same thing in every version of HTTP: the
method, path, headers and status codes from
HTTP requests and responses are
unchanged. What changed is how those requests are packed onto the network
— and each version fixed the biggest bottleneck of the one before.
HTTP/1.1: one at a time
HTTP/1.1 sends requests as plain text, and each connection handles one request at a time: send a request, wait for the whole response, then send the next.
A modern page needs dozens of files. To avoid waiting for them one by one, browsers open up to six connections per domain, each with its own TCP and TLS handshake. Developers worked around the limit with hacks: bundling everything into one huge file, image sprites, and spreading assets across several domains.
HTTP/2: many streams, one connection
HTTP/2 (2015) changed the wire format to binary frames and added multiplexing: many requests and responses share one connection at the same time, each as its own numbered stream, their frames interleaved.
- One connection per origin instead of six — one handshake.
- No waiting for one response before asking for the next.
- Header compression (HPACK) — repeated headers like cookies and user-agent aren't resent in full on every request.
Most of the old hacks became unnecessary, or even harmful.
The wall HTTP/2 hit: TCP
HTTP/2 multiplexes streams, but it runs over TCP, and TCP promises one thing: a single, ordered stream of bytes. If one packet is lost, TCP holds back everything after it until the missing packet is retransmitted — even data belonging to other streams that arrived perfectly well.
Three files — HTML, CSS, JS — are downloading at once over one connection, their packets interleaved. Both HTTP/2 and HTTP/3 multiplex streams like this. The difference is what happens when one packet is lost.
That's head-of-line blocking at the transport layer. On a good connection it rarely matters. On a lossy mobile network, one lost packet stalls every file on the page, and it happens again and again.
HTTP/3: QUIC instead of TCP
HTTP/3 keeps HTTP/2's ideas but runs over QUIC, a transport protocol built on UDP. QUIC handles reliability and ordering per stream: a lost packet delays only the stream it belongs to.
QUIC brings other improvements too:
- Faster setup. QUIC combines the transport and TLS 1.3 handshakes, so a new connection is ready in one round trip instead of two or three, and a returning visitor can often send data immediately (0-RTT).
- Connection migration. A connection is identified by an ID, not by IP address and port, so it survives switching from Wi-Fi to mobile data without starting over.
- Encryption is mandatory — there's no unencrypted HTTP/3.
Side by side
| HTTP/1.1 | HTTP/2 | HTTP/3 | |
|---|---|---|---|
| Transport | TCP | TCP | QUIC over UDP |
| Format | Text | Binary frames | Binary frames |
| Requests per connection at once | One | Many (multiplexed) | Many (multiplexed) |
| Head-of-line blocking | Per connection | At the TCP level | Only within one stream |
| New connection setup | TCP + TLS handshakes | TCP + TLS handshakes | One combined handshake |
What it means for you
- You rarely choose. Browsers and servers negotiate the version
automatically. Most CDNs and modern servers support HTTP/2 and HTTP/3
with a setting; browsers discover HTTP/3 through an
Alt-Svcheader or DNS records and switch over. - Drop the HTTP/1.1 hacks. Splitting assets across many domains now costs extra connections; giant all-in-one bundles defeat caching. Many reasonably sized files are fine.
- The biggest wins are on poor networks — mobile users and lossy connections — which are exactly the users with the slowest experience today.
In one sentence
HTTP/2 let many requests share one connection; HTTP/3 moved that connection onto QUIC, so a single lost packet no longer holds up everything else.