HTTP/1.1 → 2 → 3 — The Road to Multiplexing
Thirty years of HTTP is really one argument: how many conversations can share a single connection? Why 1.1's one-at-a-time rule created traffic jams, what HTTP/2 solved with frames and streams, why the jam simply moved one floor down, what HTTP/3 separated by swapping the foundation — and how to measure your own network before picking one.
One question, one answer — and a traffic jam
HTTP is a startlingly simple bargain. Send a request, get a response. That alone carried it for thirty years. But one condition comes attached: on a single connection, you cannot begin the next response until the current one has finished.
Picture a government office with exactly one counter. Nobody is called until the person ahead of you is done, so ten errands mean queuing ten times.
HTTP/1.0 queued up literally that way — open a connection per request, close it when the response arrives. HTTP/1.1 made connections reusable with keep-alive and added the Host header and chunked transfer. Real improvements, but the one question, one answer condition survived intact.
There was an escape hatch: pipelining, which lets you send the next request without waiting for the previous response. The catch is that responses must come back in the order they were requested. If the first request is a slow API and the second is a small image, the image cannot ship even though it is sitting ready. The front of the line stalls everything behind it — that is head-of-line blocking (HOL blocking). Too many sites broke on middleboxes that implemented it inconsistently, and major browsers ended up disabling it by default.
The brute-force fix browsers found, and its bill
If one connection is not enough, open more. Browsers settled on roughly six parallel connections per origin. The time it takes looks about like this.
is the number of assets to fetch, the number of connections you can hold open, and the time for one round trip. In plain words: more assets means proportionally more time. Once a single page routinely carried a hundred images and scripts, that was fatal.
So the industry attacked : CSS sprites gluing small images into one sheet, JS and CSS bundles, data URIs inlined straight into the HTML. The brute-force move on was domain sharding — scatter static assets across img1 and img2 to buy six connections per hostname.
But connections are not free. Each one pays for a TCP handshake and a TLS handshake, and its congestion window (the running estimate of how much may be in flight at once) starts from scratch. Open six and all six begin in the "still slow" state — and then they compete with each other for the same bandwidth.
HTTP/2 — carving several streams inside one pipe
HTTP/2, standardized in 2015 and now specified by RFC 9113, rebuilt the picture around three units. A frame is the smallest unit on the wire: a small block carrying a type, a length, and the ID of the stream it belongs to. A stream is a numbered virtual channel for one exchange (one request paired with one response). A connection is a single TCP connection, and hundreds of streams live inside it.
The decisive part is that every frame carries a stream ID. You may interleave another stream's data before finishing the current response, because the receiver just sorts by ID. The ordering constraint evaporates, and what took six connections now fits in one. Trading newline-delimited text for a binary frame format is what makes that sorting cheap and unambiguous for a machine.
Comments
Sign in to comment