Computer Networks

The Application Layer

HTTP/2, HTTP/3 and Performance

A slow response blocks every request queued

JrCodex·7 min read

Jr Codex Computer Networks Notes

Level: Intermediate–Advanced Prerequisites: Chapter 2: HTTP Fundamentals Time to complete: ~20 minutes


Table of Contents

  1. What Was Wrong With HTTP/1.1
  2. HTTP/2
  3. The Problem HTTP/2 Could Not Solve
  4. HTTP/3 and QUIC
  5. Optimisations That Became Anti-Patterns
  6. What Actually Helps
  7. Summary & Next Steps

1. What Was Wrong With HTTP/1.1

Four Structural Problems
─────────────────────────────────────────
  1. ONE REQUEST AT A TIME PER CONNECTION
     A response must complete before the next
     request may be sent on that connection.

  2. HEAD-OF-LINE BLOCKING at the application
     layer
     A slow response blocks every request queued
     behind it.

  3. THE SIX-CONNECTION WORKAROUND
     Browsers opened ~6 parallel connections per
     origin. Each pays its own TCP handshake, TLS
     handshake and slow start (Module 4).

  4. REPEATED HEADERS
     Every request resends Cookie, User-Agent,
     Accept — often 500-800 bytes, uncompressed,
     nearly identical every time.
─────────────────────────────────────────
Why Pipelining Failed
─────────────────────────────────────────
  HTTP/1.1 defined PIPELINING: send several
  requests without waiting.

  But responses had to return IN ORDER, so
  head-of-line blocking remained. And many proxies
  implemented it incorrectly.

  It was effectively never enabled by default in
  any browser. A specified feature that the
  ecosystem could not deploy — which is the same
  ossification problem QUIC was designed around
  (Module 4, Chapter 5).
─────────────────────────────────────────

2. HTTP/2

The Four Changes
─────────────────────────────────────────
  BINARY FRAMING
    The message is split into typed frames on a
    single connection, rather than being text.
    Efficient to parse, unambiguous to frame.

  MULTIPLEXING
    Many concurrent STREAMS on ONE connection.
    Requests and responses interleave freely, in
    any order.
    ── this fixes problems 1, 2 and 3 at once

  HEADER COMPRESSION (HPACK)
    A shared dynamic table on both ends. Repeated
    headers become a small index reference.
    Typical saving: 80-90% of header bytes.

  SERVER PUSH
    The server sends resources before they are
    requested.
    ── since removed; see Section 5
─────────────────────────────────────────
The Frame Layout
─────────────────────────────────────────
  Connection
    └─ Stream 1 ── HEADERS, DATA, DATA
    └─ Stream 3 ── HEADERS, DATA
    └─ Stream 5 ── HEADERS, DATA, DATA, DATA

  Frames from different streams INTERLEAVE on the
  wire:

    [S1 HDR][S3 HDR][S1 DATA][S5 HDR][S3 DATA]
    [S1 DATA][S5 DATA]...

  Each frame carries its stream ID, so the receiver
  reassembles them independently.
─────────────────────────────────────────
curl -I --http2 https://example.com          # negotiate HTTP/2
curl -w "%{http_version}\n" -o /dev/null -s https://example.com
Why One Connection Is Better
─────────────────────────────────────────
  Six connections meant six slow starts (Module 4,
  Chapter 4), six congestion windows each probing
  independently, and six sets of handshakes.

  One connection warms up once and stays warm, and
  its congestion control sees the true aggregate
  rate rather than six flows competing with each
  other.

  Better for the network AND for the client.
─────────────────────────────────────────

3. The Problem HTTP/2 Could Not Solve

TRANSPORT-LAYER HEAD-OF-LINE BLOCKING
─────────────────────────────────────────
  HTTP/2 removed head-of-line blocking at the
  APPLICATION layer. It runs on TCP, which has its
  own, at the TRANSPORT layer (Module 4,
  Chapter 5).

  TCP delivers ONE ordered byte stream. Lose one
  segment and TCP withholds EVERYTHING after it —
  including frames belonging to entirely different
  HTTP/2 streams that arrived perfectly.

  So one lost packet stalls ALL concurrent
  requests.
─────────────────────────────────────────
The Uncomfortable Consequence
─────────────────────────────────────────
  On a LOSSY network, HTTP/2's single connection
  can be SLOWER than HTTP/1.1's six.

  With six connections, a loss stalls one of them
  and five keep working. With one, everything
  stops.

  HTTP/2 is a clear win on good networks and can be
  a regression on bad ones — and mobile networks
  are frequently bad ones.

  Fixing this required replacing TCP.
─────────────────────────────────────────

4. HTTP/3 and QUIC

The Change
─────────────────────────────────────────
  HTTP/3 is HTTP/2's semantics over QUIC
  (Module 4, Chapter 5) instead of TCP.

  QUIC provides INDEPENDENT STREAMS at the
  transport layer, so a lost packet affects only
  the stream it belonged to.

  That is the whole point. Everything else QUIC
  brings is a bonus.
─────────────────────────────────────────
What HTTP/3 Gains
─────────────────────────────────────────
  NO HEAD-OF-LINE BLOCKING
    at either layer. The problem is finally solved.

  FASTER CONNECTION SETUP
    TCP + TLS = 2-3 round trips.
    QUIC = 1, or 0 when resuming.
    On a 100ms path that is 200-300ms saved on
    every new connection.

  CONNECTION MIGRATION
    Switching from wifi to mobile keeps the
    connection alive — it is identified by a
    connection ID, not the 4-tuple.

  QPACK
    Header compression redesigned so that
    out-of-order stream delivery does not create a
    new dependency between streams.
─────────────────────────────────────────
Negotiation, and Why It Is Invisible
─────────────────────────────────────────
  A server advertises HTTP/3 with the Alt-Svc
  header on an HTTP/2 response:

    Alt-Svc: h3=":443"; ma=86400

  The client connects over TCP first, sees the
  header, and uses QUIC for subsequent
  connections.

  If UDP is blocked, it silently stays on HTTP/2.
  Users never see a failure — the same
  race-and-fall-back pattern as Happy Eyeballs
  (Module 3, Chapter 2).
─────────────────────────────────────────

5. Optimisations That Became Anti-Patterns

Techniques That HTTP/2 Made HARMFUL
─────────────────────────────────────────
  DOMAIN SHARDING
    Serving assets from cdn1, cdn2, cdn3 to get
    more parallel HTTP/1.1 connections.
    NOW HARMFUL: each domain is another DNS lookup,
    another TCP and TLS handshake, another
    congestion window — and multiplexing already
    solved the parallelism problem.

  CONCATENATING FILES
    Bundling all JavaScript into one file to reduce
    request count.
    NOW COUNTERPRODUCTIVE: requests are cheap, and
    one changed line invalidates the entire bundle's
    cache. Smaller files cache far better
    (Chapter 2's hashed filenames).

  IMAGE SPRITES
    Same reasoning. Same conclusion.

  INLINING ASSETS
    Embedding CSS or images in the HTML to save a
    request. Now it just makes the HTML
    uncacheable.
─────────────────────────────────────────
SERVER PUSH — a cautionary tale
─────────────────────────────────────────
  HTTP/2's most-publicised feature. The server
  sends resources before the client asks.

  IT WAS REMOVED FROM BROWSERS.

  WHY: the server cannot know what the client
  already has cached, so it frequently pushed
  bytes that were discarded — wasting bandwidth and
  competing with resources actually needed.

  REPLACED BY:
    <link rel="preload"> — the client decides, and
    it knows its own cache
    103 Early Hints — the server SUGGESTS, the
    client chooses

  The lesson generalises: the endpoint with the
  information should make the decision.
─────────────────────────────────────────

6. What Actually Helps

Ordered by Impact
─────────────────────────────────────────
  1. REDUCE ROUND TRIPS
     Latency dominates page load (Module 1,
     Chapter 5). Every eliminated round trip is
     worth more than any bandwidth optimisation.
       - keep connections alive
       - HTTP/3 for 0-RTT resumption
       - avoid redirect chains (each is a full
         round trip)

  2. REDUCE DISTANCE
     A CDN attacks propagation delay, which is the
     one component nothing else can touch
     (Module 7, Chapter 2).

  3. CACHE PROPERLY
     A request not made costs nothing. Chapter 2's
     hashed-filename pattern.

  4. COMPRESS
     Brotli beats gzip by 15-25% on text. Both are
     essentially free.

  5. SEND LESS
     Unused JavaScript is the largest avoidable
     cost on most sites. Ship less code.

  6. PRIORITISE CORRECTLY
     Load what renders the page first; defer the
     rest.
─────────────────────────────────────────
# Where does the time actually go? (Module 1, Chapter 5's breakdown.)
curl -w "dns:%{time_namelookup} connect:%{time_connect} \
tls:%{time_appconnect} ttfb:%{time_starttransfer} total:%{time_total} \
proto:%{http_version}\n" -o /dev/null -s https://example.com
The Discipline
─────────────────────────────────────────
  Measure before optimising, and measure on a
  REALISTIC connection.

  Everything looks fast on a 1 Gbps office link
  with 5ms latency. Test with throttling that
  matches your users — mobile latency is 50-200ms,
  and that is where round trips hurt.

  Most sites are slow because of round trips and
  payload size, not because of protocol version.
─────────────────────────────────────────

7. Summary & Next Steps

Key Takeaways

  • HTTP/1.1 allowed one outstanding request per connection, which browsers worked around with six connections, each paying its own handshakes and slow start.
  • HTTP/2's multiplexing fixed application-layer head-of-line blocking but inherited TCP's, so one lost packet stalls every concurrent request.
  • HTTP/3 over QUIC gives independent transport streams, one-round-trip setup and connection migration — solving the problem HTTP/2 structurally could not.
  • Sharding, bundling and sprites were HTTP/1.1 workarounds that are now counterproductive, and server push failed because the server cannot know the client's cache.

Concept Check

  1. Why can HTTP/2 be slower than HTTP/1.1 on a lossy mobile network?
  2. Why did concatenating all JavaScript into one bundle stop being a good idea?
  3. Why was server push removed, and what replaced it?

Next Chapter

Chapter 4: REST, WebSockets and Real-Time


Jr Codex — 1-on-1 Personalized Coaching | Back to Module Index | Back to Computer Networks Index