Beyond Code & Karma · Networking
Many streams, one connection. How HTTP/2 interleaves dozens of requests as frames to defeat HTTP/1.1's head-of-line blocking — and where HTTP/3 and QUIC carry the idea further. The transport choice that decides how fast a page paints.
Chapter 01 — The Foundation
A modern page pulls dozens of resources — HTML, CSS, JavaScript, fonts, images. Multiplexing is how a protocol lets those requests share one connection at the same time instead of queuing. HTTP/1.1 sends one request-response per connection at a time, so a slow response blocks everything behind it — head-of-line blocking. HTTP/2 breaks each request into frames tagged with a stream ID and interleaves them over a single connection, so every stream makes progress together.
The Cosmic Connection
In the Vedic image of Indra's net, reality is a vast web with a jewel at every knot, and each jewel reflects all the others — many distinct things, held as one fabric. The Upanishads say the many are strung on the one like beads on a single thread (sutra), as many rivers lose their names in one ocean without ceasing to be themselves. HTTP/2 is exactly this: unity-in-diversity on the wire.
"Multiplexing is unity-in-diversity: the many made one, without any one losing its distinctness."
Chapter 02 — On The Wire
The clearest way to feel multiplexing is to look at the request waterfall — HTTP/1.1 serializes, HTTP/2 overlaps. Then check what your own origin actually negotiates.
HTTP/1.1 opens roughly six connections and serializes requests inside each; HTTP/2 puts everything on one connection as interleaved frames:
# HTTP/1.1 — browser opens ~6 connections, requests serialize inside each. # Each [====] is one request occupying its connection end-to-end. conn-1 [==html==][===app.js===][==logo.png==] conn-2 [==app.css==][==hero.jpg==] conn-3 [==font.woff2==] # └─ a slow response holds the whole connection: head-of-line blocking. # HTTP/2 — ONE connection, every request interleaved as frames. conn-1 [html][css][js][img][font][js][img][html]... # all in flight together # └─ no request waits behind another. App-layer HOL blocking is gone.
ALPN negotiates h2 during the TLS handshake; HTTP/3 advertises itself
with an alt-svc header and upgrades on the next visit:
# Which wire protocol is an origin actually serving? # -I = headers only; --http2 negotiates h2 over TLS via ALPN. curl -I --http2 https://beyondcodekarma.in # The status line names the protocol on the wire: # HTTP/2 200 ← one TCP + TLS connection, fully multiplexed # HTTP/3 advertises itself in a response header, then upgrades: # alt-svc: h3=":443"; ma=86400 curl -I --http3 https://cloudflare.com
A new request opens a stream with its own ID over the single existing connection — no new handshake, no new socket.
Headers and body are sliced into small frames, each stamped with that stream ID so it never loses its identity.
Frames from every active stream are interleaved on the one connection, so all requests advance together — the many as one.
The receiver groups frames by stream ID and rebuilds each response independently. No stream waited in line for another.
Chapter 03 — Live Visualization
Four requests race across the wire on each protocol, auto-playing. HTTP/1.1 sends them one at a time; HTTP/2 interleaves all four at once and finishes first.
Chapter 04 — Deep Dive
This is where the basic explainers stop. Here's the part that decides real-world tail latency.
| Property | HTTP/1.1 | HTTP/2 | HTTP/3 |
|---|---|---|---|
| Connections / origin | ~6 parallel | 1 | 1 (QUIC) |
| Multiplexing | None — serial per conn | Yes — interleaved frames | Yes — independent streams |
| App-layer HOL blocking | Yes | No | No |
| Transport HOL blocking | Per connection | Yes (one TCP stream) | No (per-stream delivery) |
| Transport | TCP + TLS | TCP + TLS | QUIC over UDP |
HTTP/2 removes the application-layer queue, but it still rides a single TCP connection — and TCP delivers its byte stream strictly in order. If one packet is lost, the receiver must hold back every byte that arrived after it, including frames belonging to completely unrelated streams, until that one packet is retransmitted. So under packet loss, HTTP/2's "everything in parallel" becomes "everything frozen together". That is transport-layer HOL blocking, and it is the exact reason HTTP/3 exists.
HTTP/3 keeps multiplexing but swaps the transport for QUIC, built on UDP. QUIC implements its own loss recovery with independent streams — each stream carries its own delivery ordering. A packet lost on one stream stalls only that stream; the others keep flowing, because they were never waiting on it.
1-RTT or
0-RTT), so connections start faster and are encrypted
by default — separate boats and a quicker launch.
HTTP/3's big win is under packet loss and on lossy or high-latency networks — mobile, congested links — where killing transport HOL blocking and using a faster handshake genuinely helps. On a clean, low-loss wired connection the difference is often small, and QUIC's user-space processing can cost slightly more CPU than the kernel's highly tuned TCP stack. It improves real-world tail latency; it is not a universal speed-up. Measure before assuming.
HTTP/1.1 hacks were all about beating the ~6-connection ceiling: domain sharding (serve assets from many subdomains to open more connections), image sprites, and concatenating CSS/JS into giant bundles. Under HTTP/2 these become counter-productive — sharding multiplies expensive connections and defeats a single congestion-control context, and mega-bundles hurt caching granularity. With cheap multiplexed streams, smaller, independently-cacheable files win.
It's the default transport for most of the modern web:
| System | What multiplexing buys it |
|---|---|
| CDNs (Cloudflare, Fastly) | HTTP/2 & HTTP/3 at the edge — resilient delivery under real-world loss. |
| Browsers | One connection per origin replaces six; better congestion control, faster paints. |
| gRPC | Built directly on HTTP/2 streams for bidirectional, multiplexed RPC. |
| Mobile networks | HTTP/3 contains packet-loss damage to one stream, smoothing tail latency. |
Chapter 05 — Dharma & The Wire
Multiplexing is the discipline of holding the many as one — the connection is the single thread, the streams are the jewels of Indra's net strung upon it. But to bind many fates to one vessel is also to share its karma:
// One connection — the single thread on which the many are strung. const conn = connect('h2'); // the one // Many streams — distinct jewels in Indra's net, each reflecting // all the others, yet all carried as a single interleaved flow. streams.forEach(s => conn.send(s.frames)); // the many // HTTP/1.1: the narrow ford — one slow pilgrim blocks the road. // HTTP/2: the many made one, without losing their distinctness.
When the shared boat strikes a rock — a lost packet — all aboard are bound to wait together. That is shared karma: TCP head-of-line blocking. To give each pilgrim a separate boat (HTTP/3, QUIC) is not selfishness; it is the discipline of not entangling one soul's delay with another's journey. Bear your own loss, and let the others keep flowing.
"The many made one is grace; the one made to suffer for all is the cost. Choose the binding wisely." — interpreted for systems engineers 🙏
Chapter 06 — Test Yourself
Three questions. No cheating. Your karma is watching.
The Enlightenment
कर्म करो, फल की चिंता मत करो