QuestionsNetworking/Security

HTTP/1.1 vs HTTP/2 vs HTTP/3

Protocol EvolutionMediumNetworking/Security

Compare HTTP/1.1, HTTP/2, and HTTP/3. What problem does each version solve, and what is head-of-line blocking?

What it tests

Understanding how the protocol evolved to fix connection/latency bottlenecks, and where head-of-line blocking moves at each step.

Approach & answer

Each HTTP version attacks the previous one's bottleneck. HTTP/1.1 sends one request at a time per TCP connection: a response must complete before the next request on that connection starts. This is APPLICATION-LAYER head-of-line (HOL) blocking — a slow response stalls everything queued behind it. The historical workaround was opening 6-ish parallel connections per origin (costly: each needs its own TCP + TLS handshake) plus hacks like domain sharding, spriting, and concatenating files to reduce request count. HTTP/2 introduced MULTIPLEXING: many concurrent request/response STREAMS interleaved over a SINGLE TCP connection, using binary framing. That kills application-layer HOL blocking and removes the need for sharding/spriting (one connection, many parallel streams). It also added HEADER COMPRESSION (HPACK — headers repeat heavily across requests) and server push (largely deprecated in practice). But HTTP/2 still runs on TCP, and TCP guarantees in-order delivery of its byte stream — so if ONE packet is lost, TCP holds back ALL streams' data until it's retransmitted, even streams that had no loss. That's TCP-level (transport) HOL blocking: H2 solved it at the app layer but TCP reintroduced it underneath, and it bites hardest on lossy/mobile networks. HTTP/3 fixes that by abandoning TCP for QUIC, a protocol built on UDP. QUIC implements streams itself with INDEPENDENT loss recovery, so a lost packet only stalls the stream it belongs to, not the others — finally eliminating transport HOL blocking. QUIC also folds the transport + TLS 1.3 handshake together for faster (often 1-RTT, or 0-RTT on resumption) connection setup, and its connection ids let a connection survive network changes (Wi-Fi to cellular) without re-handshaking. The practical implications for frontend: with H2/H3 the old 'bundle everything into one file' advice weakens — many smaller cacheable files parallelize fine — though there's still per-request overhead, so extreme fragmentation isn't free. You generally get H2/H3 for free from your CDN/host; the main thing to know is WHY (multiplexing removed the connection-count tax, QUIC removed the last HOL bottleneck).

Use this technique when

Explaining why bundling advice changed; reasoning about multiplexing; discussing HOL blocking.

Code

HTTP/1.1  one request at a time per connection
          -> APP-layer HOL blocking; workaround: ~6 connections + sharding/spriting

HTTP/2    multiplexed streams over ONE TCP connection + HPACK header compression
          -> removes app-layer HOL blocking & the connection-count tax
          -> BUT still on TCP: one lost packet stalls ALL streams (TCP-level HOL)

HTTP/3    QUIC (over UDP) with per-stream loss recovery + TLS 1.3 built in
          -> lost packet stalls only its own stream (no transport HOL)
          -> faster handshake (1-RTT / 0-RTT), connection survives network switch

Frontend takeaway: with H2/H3, "bundle it all into one file" matters far less —
many small cacheable files parallelize well.

References