What Does HTTP/2 Actually Change Compared to HTTP/1.1?

HTTP/2 keeps the same request methods, status codes and header fields as HTTP/1.1, so nothing about your application logic has to change. What it replaces is the transport behaviour: instead of one request per connection at a time, HTTP/2 carries many independent requests and responses over a single connection as interleaved binary frames. That single change removes most of the latency that HTTP/1.1 forced developers to work around with domain sharding, sprite sheets and concatenated files.

Multiplexing: many requests, one connection

In HTTP/1.1, a connection handles one request-response exchange at a time. Browsers open around six parallel connections per origin to compensate, but each connection is still serialised: if a slow response is in flight, everything queued behind it on that connection waits. This is application-level head-of-line blocking.

HTTP/2 breaks each message into frames and tags every frame with a stream identifier. Frames from different streams are interleaved on the same TCP connection and reassembled by the receiver. A large image download no longer blocks a small CSS file; both progress concurrently.

Practical consequences:

  • Domain sharding becomes counterproductive. Splitting assets across static1., static2. and static3. subdomains was an HTTP/1.1 trick to get more connections. Under HTTP/2 it costs extra DNS lookups, extra TLS handshakes and loses connection-level compression benefits.
  • Concatenation and spriting matter less. Bundling 30 files into one was a workaround for connection limits. With multiplexing, many small files are usually fine — though each request still carries overhead, so moderate bundling is still reasonable.
  • One connection per origin is the goal. Fewer connections means less handshake cost and better use of the congestion window.

What multiplexing does not fix

HTTP/2 runs over TCP, and TCP itself is a single ordered byte stream. If a TCP segment is lost, the kernel holds back all later bytes until the retransmission arrives — including bytes belonging to unrelated streams. This is TCP-level head-of-line blocking, and HTTP/2 cannot avoid it. On a clean network it rarely matters; on lossy mobile links it can erase much of the gain. This limitation is the main motivation for HTTP/3, which runs over QUIC instead of TCP.

Header compression with HPACK

Every HTTP request repeats headers: User-Agent, Cookie, Accept, Accept-Encoding and so on. In HTTP/1.1 these are sent as plain text on every single request, and cookies in particular can add hundreds of bytes per request.

HTTP/2 uses HPACK, which combines two techniques:

  1. Static and dynamic tables. Common header names and values have fixed indices. Both peers also maintain a dynamic table of headers seen on that connection, so a repeated User-Agent can be sent as a short index rather than the full string.
  2. Huffman coding for literal values that are not in a table.

The effect is largest on sites with many requests and large cookies. A page issuing 80 requests with a 1 KB cookie each sends roughly 80 KB of cookie data under HTTP/1.1; under HTTP/2, after the first request, that cookie is largely replaced by table references.

One caveat worth knowing: HPACK's dynamic table is per-connection and stateful, which is why header compression is one reason HTTP/2 is effectively TLS-only in browsers — intermediaries that can't see the state can't safely rewrite headers.

Server push and stream prioritisation

Server push lets the server send a resource the client hasn't asked for yet, anticipating that it will need it — for example, pushing app.css when index.html is requested. In theory this saves a round trip.

In practice, push has proven difficult to use well:

  • The server may push something already in the browser cache, wasting bandwidth.
  • Pushed resources compete with the HTML itself for bandwidth.
  • Getting the dependency graph right requires per-page knowledge that is easy to get wrong.

Chrome removed support for HTTP/2 push, and it is widely regarded as a feature to use sparingly or not at all. The modern replacement is <link rel="preload">, which lets the client decide, plus 103 Early Hints responses that tell the browser what to fetch while the main response is still being generated.

Stream prioritisation lets the client express which streams matter more, via a dependency tree (in the original specification) or the simpler urgency-and-incremental scheme used by many current implementations. Support has been inconsistent, and in practice most servers and CDNs implement their own scheduling heuristics. Treat prioritisation as a nice-to-have rather than something to design around.

TLS, ALPN and how HTTP/2 gets negotiated

Browsers only speak HTTP/2 over TLS. The negotiation happens during the TLS handshake using ALPN (Application-Layer Protocol Negotiation): the client offers h2 and http/1.1, and the server picks one. If the server doesn't advertise h2, the connection silently falls back to HTTP/1.1 — which is why "HTTP/2 enabled" can look true in a config file but never actually be used.

Requirements to check on the server side:

  • TLS 1.2 or newer with a cipher suite that HTTP/2 permits (forward-secret suites are effectively required; the old RSA key-exchange suites are not allowed).
  • ALPN support in the TLS library. Older OpenSSL builds lack it.
  • No renegotiation, which HTTP/2 forbids.
  • A modern browser — every current major browser supports HTTP/2.

The unencrypted variant, h2c, exists in the specification but no browser implements it, so it is only relevant for internal service-to-service traffic.

HTTP/2 versus HTTP/3

These are often confused, so keep the distinction clear:

HTTP/1.1 HTTP/2 HTTP/3
Transport TCP TCP QUIC (over UDP)
Multiplexing No Yes, per connection Yes, per connection
TCP head-of-line blocking Yes Yes No
Header compression None HPACK QPACK
Encryption in browsers Optional Required in practice Built in
Negotiation ALPN h2 ALPN h3, plus an Alt-Svc hint

HTTP/3 is not a replacement for HTTP/2 in the sense that HTTP/2 replaced HTTP/1.1's connection model; it keeps the same framing concepts and swaps the transport. Many servers now support both and let the client choose. If your server offers HTTP/3, browsers will typically use it after learning about it via an Alt-Svc header, and fall back to HTTP/2 otherwise.

Is enabling it worth it?

For most sites, yes, and the cost is low. The gains are largest when:

  • You serve many small resources per page.
  • Requests carry large cookies or long header sets.
  • Clients are on low-latency, low-loss connections where TCP-level blocking rarely triggers.

The gains are smallest when:

  • Your pages are already heavily bundled into a handful of large files.
  • Your bottleneck is server processing time or database queries, not network round trips.
  • Your users are predominantly on lossy mobile networks, where HTTP/3 would help more.

A practical checklist

  1. Confirm your TLS configuration meets HTTP/2's requirements (TLS 1.2+, forward-secret ciphers, ALPN).
  2. Enable HTTP/2 in the web server or load balancer configuration.
  3. Verify with a browser's developer tools — the protocol column should read h2 — or with a command-line client that reports the negotiated protocol.
  4. Revisit HTTP/1.1-era optimisations: consider dropping domain sharding, and re-evaluate aggressive concatenation.
  5. Avoid server push unless you have measured a specific benefit; prefer preload and 103 Early Hints.
  6. If lossy mobile performance matters, evaluate HTTP/3 alongside HTTP/2 rather than instead of it.

The short version: HTTP/2 changes how bytes travel, not what you send. Multiplexing and HPACK remove the connection-level bottlenecks that shaped a decade of front-end optimisation advice, while TCP's own ordering guarantee remains the ceiling that HTTP/3 was designed to lift.

litespeedtech.com
LiteSpeed provides one-stop web-acceleration solutions that embrace and advance cutting-edge technologies. Web server, load balancer, cache solutions…