⚡ HTTP/2

Same semantics, new plumbing: a binary framing layer that multiplexes many requests over one connection — and still trips on the TCP it rides.

The One Big Idea: A Framing Layer

HTTP/2 keeps every HTTP semantic — methods, headers, status codes — but stops sending them as text. Instead it inserts a binary framing layer between the application and TCP. A request/response is chopped into typed frames that flow over logical streams, all sharing a single TCP connection.

flowchart TB subgraph Conn["1 TCP connection"] direction TB S1["Stream 1: HEADERS + DATA (/a)"] S3["Stream 3: HEADERS + DATA (/b)"] S5["Stream 5: HEADERS + DATA (/c)"] end Note["frames from all streams
are interleaved on the wire"] Conn --> Note
Frame = the atom of HTTP/2. Every frame has a type (HEADERS, DATA, SETTINGS, WINDOW_UPDATE, RST_STREAM, …), a length, flags, and a stream ID. Because each frame is tagged with its stream, the receiver can pull them apart no matter how they're interleaved.

Multiplexing: Many Streams, One Connection

This kills the HTTP/1.1 workarounds in one move. Dozens of requests ride concurrently over a single connection — no more 6-connection cap, no domain sharding, no bundling everything into one giant file to save round trips.

Streams are independent and bidirectional. Client-initiated streams use odd IDs, server-initiated use even. A slow response no longer blocks the others at the HTTP layer — the server can send /b's frames while /a is still computing.

HTTP/1.1HTTP/2
Requests per connectionOne at a timeMany, interleaved
Connections per origin~61
Response orderingStrict (FIFO)Any order, per-stream

HPACK: Header Compression

Headers are repetitive and huge. Every request re-sends Cookie, User-Agent, Accept… often more bytes than the request itself. Text HTTP/1.1 had no way to compress them safely.

HPACK compresses headers with two tricks:

Why not just gzip the headers? Compressing attacker-influenced data mixed with secrets (like cookies) enables the CRIME attack. HPACK was designed to be compression that resists that class of leak — a lesson HTTP/3's QPACK carries forward.

Stream Prioritization & Flow Control

With everything on one connection, the client needs to say what matters first — HTML and CSS before a below-the-fold image. HTTP/2 defined a priority tree (dependencies + weights) so the server could allocate bandwidth sensibly.

Reality check: the original priority scheme was complex and implemented inconsistently across servers and browsers, so much of it was later deprecated in favor of a simpler scheme. Treat fine-grained prioritization as best-effort, not a guarantee.

Flow control (via WINDOW_UPDATE frames) is per-stream and per-connection — a receiver can slow a firehose stream without stalling the whole connection.

Server Push (and its retirement)

HTTP/2 let a server push resources the client hadn't asked for yet — send style.css alongside index.html before the browser parses the link.

Why it was deprecated: servers routinely pushed things the client already had cached, wasting bandwidth. It was hard to use correctly, browsers removed support, and the ecosystem moved to <link rel="preload"> and 103 Early Hints instead. Don't design around server push.

The Catch: TCP Head-of-Line Blocking

HTTP/2 solved HOL blocking at the HTTP layer but not at the transport layer. All streams share one TCP connection, and TCP guarantees in-order, reliable byte delivery. If a single TCP segment is lost, TCP stalls delivery of everything behind it — including frames belonging to completely unrelated streams — until the retransmission arrives.
flowchart LR L["Lost TCP segment (stream 1)"] --> K["TCP kernel buffers everything after it"] K --> B["Streams 3, 5, 7 frames arrive
but can't be delivered to the app"] B --> W["all streams wait for one retransmit"]

So on a lossy network, HTTP/2 can be worse than six independent HTTP/1.1 connections, because those connections fail independently. This is the exact problem HTTP/3 was created to solve — see the head-of-line blocking deep-dive.

Key Takeaways

MechanismWhat it buys
Binary framesFast, unambiguous parsing; strict framing
Streams + multiplexingMany concurrent requests, one connection
HPACKHeader sizes cut dramatically, safely
Flow controlPer-stream backpressure
TCP underneathStill one shared byte-stream → transport HOL blocking
Real-world: HTTP/2 is a huge win on stable connections and is the default for gRPC (whose streaming maps directly onto HTTP/2 streams). Its one unfixable weakness — sharing a single TCP stream — is precisely what pushed the industry to rebuild the transport in HTTP/3.