Modern Web Networking: HTTP/2 Multiplexing, HTTP/3 QUIC, WebSockets, and Server-Sent Events
Deconstructing binary framing, transport head-of-line blocking, QUIC UDP encryption, and real-time streaming protocols
Part 4 in Series — Catch up on the previous article: TypeScript for System Design: Advanced Type Mechanics, Nominal Branding, and Turing Completeness (Part 3) before diving into this post.
Network communication forms the core pipeline of client-side web application latency. For decades, web developers worked within the constraints of HTTP/1.1—implementing domain sharding, image spriting, and manual resource concatenation to work around browser connection limits and head-of-line blocking.
Modern frontend web architecture relies on advanced transport protocols: HTTP/2 binary multiplexing, HTTP/3 QUIC over UDP, WebSockets, and Server-Sent Events (SSE).
1. HTTP/1.1 vs HTTP/2: Binary Framing & Multiplexing
HTTP/1.1 processes requests over plain-text streams. Because a single TCP connection can only handle one request-response exchange at a time, browsers enforced a strict limit of 6 concurrent TCP connections per origin.
HTTP/2 introduced the Binary Framing Layer, breaking requests and responses into discrete binary frames (DATA, HEADERS, SETTINGS, RST_STREAM) interleaved over a single TCP connection.
HTTP/1.1 (Sequential Request Blocking):
TCP Conn 1: [ Req 1: style.css ] --------> [ Resp 1: style.css ] ---> [ Req 2: app.js ]
TCP Conn 2: [ Req 3: logo.png ] --------> [ Resp 3: logo.png ]
HTTP/2 (Binary Multiplexing over Single TCP Connection):
Single TCP: [ Frame: Stream 1 (CSS) ][ Frame: Stream 3 (JS) ][ Frame: Stream 1 (CSS) ]
1.1 HPACK Header Compression
HTTP/1.1 sends verbose text headers (User-Agent, Cookie, Accept) with every single request, introducing multi-kilobyte overhead.
HTTP/2 uses HPACK Header Compression:
- Both client and server maintain a shared Static Table (common headers indexed 1–61) and a dynamic Dynamic Table (custom headers added during connection lifetime).
- Instead of resending
"User-Agent: Mozilla/5.0..."on every request, the client transmits a 1-byte indexed reference pointer.
2. HTTP/2 Transport HOL Blocking vs HTTP/3 QUIC
While HTTP/2 solves application-layer head-of-line blocking, it introduces Transport-Layer Head-of-Line (HOL) Blocking at the TCP layer.
Because TCP guarantees strict in-order packet delivery:
- If a single TCP packet carrying Frame Stream 3 is dropped on an unreliable Wi-Fi connection, the operating system kernel blocks all streams (Stream 1, Stream 2, Stream 4) in the TCP buffer until the lost packet is retransmitted.
TCP Layer HOL Blocking (HTTP/2):
[ Packet 1 (Stream 1) ][ Packet 2 (DROPPED) ][ Packet 3 (Stream 3) ]
|
v
OS Kernel STALLS ALL Streams waiting for Packet 2 retransmission!
2.1 HTTP/3 & QUIC (Quick UDP Internet Connections)
HTTP/3 solves transport-layer HOL blocking by replacing TCP with QUIC, an encrypted transport protocol operating on top of UDP.
HTTP/2 Stack: HTTP/3 Stack:
+-------------------+ +-------------------+
| HTTP/2 | | HTTP/3 |
+-------------------+ +-------------------+
| TLS 1.3 | | QUIC (Built-in |
+-------------------+ | TLS 1.3 + Cong) |
| TCP | +-------------------+
+-------------------+ | UDP |
| IP | +-------------------+
+-------------------+ | IP |
+-------------------+
- Independent Streams: QUIC implements stream multiplexing directly at the transport layer. A dropped UDP packet in Stream 1 only stalls Stream 1; Stream 2 and Stream 3 continue processing without delay.
- 0-RTT Connection Establishment: TLS 1.3 is embedded directly inside the QUIC handshake. Re-connecting clients can send encrypted request data on the very first packet exchange (0-RTT).
- Connection Migration: QUIC identifies sessions using a 64-bit Connection ID rather than an IP/Port 4-tuple. When a mobile device switches from Wi-Fi to 5G cellular, the QUIC connection stays alive without dropping or re-handshaking.
3. Real-Time Streaming: WebSockets vs Server-Sent Events (SSE)
Choosing the correct real-time architecture requires analyzing directional data flow requirements:
| Feature | WebSockets (ws://, wss://) | Server-Sent Events (EventSource) |
|---|---|---|
| Data Direction | Full-Duplex (Client <---> Server) | Unidirectional (Server ---> Client) |
| Underlying Protocol | Custom TCP Frame Protocol (HTTP Upgrade) | Standard HTTP/2 or HTTP/1.1 |
| Reconnection | Manual implementation required | Built-in automatic retry & Last-Event-ID |
| Binary Support | Native (ArrayBuffer, Blob) | Text only (UTF-8 payload) |
| HTTP Infrastructure | Bypasses standard HTTP proxies/firewalls | Reuses standard HTTP load balancers/CDNs |
3.1 Server-Sent Events (SSE) Production Client Implementation
For real-time dashboards, stock tickers, or AI stream completions where the client only reads server updates:
// Production Resilient SSE Connection Architecture
export class ResilientEventStream {
private eventSource: EventSource | null = null;
private reconnectAttempts = 0;
private maxReconnectAttempts = 5;
constructor(private url: string) {}
public connect(onMessage: (data: unknown) => void) {
this.eventSource = new EventSource(this.url);
// Standard SSE message listener
this.eventSource.onmessage = (event: MessageEvent) => {
this.reconnectAttempts = 0; // Reset counter on success
const parsedData = JSON.parse(event.data);
onMessage(parsedData);
};
// Custom named SSE event listener
this.eventSource.addEventListener("telemetry-update", (event: MessageEvent) => {
console.log("Telemetry Payload:", event.data);
});
this.eventSource.onerror = (err) => {
console.error("SSE Connection Error. Reconnecting...", err);
if (this.eventSource?.readyState === EventSource.CLOSED) {
this.handleReconnect(onMessage);
}
};
}
private handleReconnect(onMessage: (data: unknown) => void) {
if (this.reconnectAttempts < this.maxReconnectAttempts) {
this.reconnectAttempts++;
const delay = Math.pow(2, this.reconnectAttempts) * 1000;
setTimeout(() => this.connect(onMessage), delay);
}
}
public disconnect() {
if (this.eventSource) {
this.eventSource.close();
this.eventSource = null;
}
}
}
Summary & Key Takeaways
- HTTP/2: Introduced binary framing and multiplexing over a single TCP connection, eliminating domain sharding and connection limits.
- HPACK Compression: Eliminates repetitive HTTP header overhead using static and dynamic index tables.
- HTTP/3 (QUIC): Replaces TCP with UDP to eliminate transport-layer head-of-line blocking and enable 0-RTT handshakes and connection migration across networks.
- WebSockets vs SSE: Use WebSockets for bidirectional interactive applications (chat, collaborative drawing). Use Server-Sent Events (SSE) for unidirectional server broadcasts (live telemetry, AI response streaming) due to native auto-reconnection and HTTP compatibility.
References & Further Reading
- IETF. RFC 9113: HTTP/2 Infrastructure Specification. IETF Standard.
- IETF. RFC 9114: HTTP/3 Protocol & QUIC Transport. IETF Standard.
- WHATWG. Server-Sent Events Specification. WHATWG Standard.
Part 5: React Architecture Under the Hood: Fiber Tree Reconciliation, Priority Scheduling, and Concurrent Mode
Continue to Part 5 →