TL;DR: HTTP/2 keeps HTTP semantics but changes transport behavior significantly: multiplexing replaces many HTTP/1.1 connection workarounds, and the migration question is usually about performance tradeoffs, not application semantics.
The Practical Question
Most teams are not deciding whether they like binary frames more than text. They are deciding whether old HTTP/1.1 performance habits still make sense.
The short answer is usually no.
The Core Difference
HTTP/1.1 and HTTP/2 keep the same HTTP semantics: methods, headers, status codes, and bodies still mean the same things. The big change is in how those messages move over the connection.
HTTP/1.1 uses a text-based protocol. Each request/response is a sequence of human-readable lines. Each connection handles one request at a time; HTTP/1.1 pipelining exists in RFC 9112 but is disabled in browsers because of head-of-line blocking and broken proxies.
HTTP/2 uses a binary framing layer. Messages are split into frames and multiplexed over a single connection. Multiple requests and responses can be in-flight simultaneously without blocking each other.
Key Differences
| Feature | HTTP/1.1 | HTTP/2 |
|---|---|---|
| Protocol format | Text | Binary frames |
| Multiplexing | No (one request per connection) | Yes (multiple streams) |
| Header compression | None (plain text) | HPACK |
| Server push | No | Defined in RFC 9113, but removed from Chrome 106 and effectively dead |
| Connection reuse | Keep-Alive (limited) | Single connection per origin |
| TLS required | No | No (spec), Yes (browsers) |
| Head-of-line blocking | HTTP + TCP level | TCP level only |
Multiplexing
The biggest practical improvement in HTTP/2 is multiplexing. In HTTP/1.1, browsers open up to 6 parallel TCP connections per host to work around the one-request-per-connection limit. Each connection has its own TLS handshake overhead.
HTTP/2 opens a single connection per origin and sends all requests as independent streams over it. Streams are interleaved at the frame level — a slow response on stream 3 does not block stream 5.
This makes HTTP/1.1 performance tricks like domain sharding and request bundling unnecessary and counterproductive.
Header Compression
HTTP/1.1 sends full headers on every request. For a page with 50 resources, the browser sends the same Cookie, User-Agent, Accept-Encoding, and Authorization headers 50 times.
HTTP/2 HPACK compression maintains a dynamic table of previously seen headers. Repeated headers are sent as a single index byte instead of the full string. The gain is largest for requests with big, repeated Cookie and Authorization values. HPACK is deliberately designed to resist the CRIME-style compression attacks that broke TLS-level header compression.
Migration Considerations
HTTP/2 is negotiated via ALPN during the TLS handshake — no URL changes, no code changes for most applications. Clients that don’t support HTTP/2 automatically fall back to HTTP/1.1.
What to stop doing when moving to HTTP/2:
- Domain sharding (defeats connection reuse)
- Aggressive JS/CSS bundling (makes caching less granular)
- Inlining small assets (HTTP/2 handles many small files efficiently)
- Sprite sheets (same reason)
What still matters:
- Caching headers (HTTP/2 doesn’t change caching semantics)
- Compression (gzip/brotli for response bodies)
- CDN usage (HTTP/2 is most effective at the edge)
What This Means In Practice
If your frontend build strategy still reflects old HTTP/1.1 bottlenecks, HTTP/2 is often a reason to simplify rather than add more bundling and sharding tricks. The protocol upgrade does not fix bad caching or oversized assets, but it does remove some of the transport pain those old workarounds were compensating for.
HTTP/3
HTTP/3 (RFC 9114) runs the same semantics over QUIC (RFC 9000) on UDP, which removes TCP-level head-of-line blocking: a lost packet stalls only the stream it belongs to. QUIC integrates TLS 1.3 and can resume with 0-RTT, which is replayable and should be limited to safe requests. Browsers discover it through the Alt-Svc: h3=":443" response header or an HTTPS DNS record, and fall back to HTTP/2 when UDP/443 is blocked. All major browsers and CDNs (Cloudflare, CloudFront, Fastly) support it. See the HTTP/3 and QUIC guide for setup and verification.
Enable and verify
nginx 1.25.1 and later deprecated the http2 flag on listen; use the separate directive:
server {
listen 443 ssl;
http2 on;
server_name example.com;
}
Older configs with listen 443 ssl http2; still work but log a deprecation warning. Check what a server negotiates:
curl -sI --http2 https://example.com | head -1 # HTTP/2 200
curl -sI --http1.1 https://example.com | head -1 # HTTP/1.1 200 OK
curl -sI --http3 https://example.com | head -1 # needs a curl built with HTTP/3
curl -sv prints the ALPN result (ALPN: server accepted h2) and Chrome DevTools shows it in the Protocol column (h2, h3).
FAQ
Does HTTP/2 require HTTPS?
Not by the spec, but in practice yes. All major browsers only implement HTTP/2 over TLS (h2). The plaintext version (h2c) exists in the spec but is not supported by browsers. If you want HTTP/2 in a browser context, you need HTTPS.
What is head-of-line blocking and does HTTP/2 fix it?
In HTTP/1.1, a slow response blocks all subsequent responses on the same TCP connection (head-of-line blocking). HTTP/2 fixes this at the HTTP layer with multiplexing — multiple streams share one connection without blocking each other. However, TCP-level head-of-line blocking still exists in HTTP/2. HTTP/3 (QUIC) eliminates it entirely.
Should I still use domain sharding or asset bundling with HTTP/2?
No. Domain sharding (splitting assets across multiple domains to open more TCP connections) and aggressive bundling were HTTP/1.1 workarounds for connection limits. With HTTP/2 multiplexing, they are counterproductive — sharding defeats connection reuse and bundling makes caching less granular. Serve assets from a single origin and let HTTP/2 multiplex them.
What is HPACK and why does it matter?
HPACK is the header compression algorithm used in HTTP/2. HTTP/1.1 sends headers as plain text on every request, including large cookies and User-Agent strings. HPACK maintains a shared compression table between client and server, so repeated headers (like Authorization or Cookie) are sent as short index references instead of full strings. This significantly reduces overhead for API-heavy applications.
Is HTTP/2 server push worth using?
Mostly no, in practice. Server push lets the server proactively send resources (e.g., CSS, JS) before the client requests them. However, it is difficult to implement correctly without over-pushing already-cached resources, and Chrome removed support for it in version 106 (2022). The 103 Early Hints status code is the modern replacement for the same use case.