HTTP/3 is the third major version of the Hypertext Transfer Protocol, designed to improve performance and reliability by running over QUIC instead of TCP. It represents a fundamental shift in how HTTP traffic is transported while maintaining compatibility with existing HTTP semantics.
Evolution of HTTP Transport
HTTP/1.1 Limitations
HTTP/1.1 uses text-based, whitespace-delimited message framing that is human-readable but computationally expensive to parse. The protocol lacks native multiplexing support, requiring multiple TCP connections to achieve parallelism. This approach degrades congestion control effectiveness and increases connection overhead.
Key characteristics: - Plain-text message format with verbose headers - One request per connection without pipelining support - Multiple connections required for concurrent requests - No header compression mechanism
HTTP/2 Improvements and Remaining Issues
HTTP/2 introduced binary framing and stream multiplexing over a single TCP connection, significantly improving efficiency. However, it inherited TCP's head-of-line blocking problem: packet loss on any stream stalls all multiplexed streams until retransmission occurs.
Improvements over HTTP/1.1: - Binary framing layer for efficient parsing - Stream multiplexing with priority signaling - Header compression using HPACK - Server push capability
Limitations: - TCP head-of-line blocking affects all streams - Connection establishment requires separate TCP and TLS handshakes - Limited resilience to network path changes
QUIC as the Transport Foundation
QUIC addresses HTTP/2's limitations by providing stream multiplexing at the transport layer with independent stream reliability. Built on UDP, QUIC integrates TLS 1.3 directly into the protocol, enabling faster connection establishment and 0-RTT resumption.
QUIC features leveraged by HTTP/3: - Per-stream flow control and independent loss recovery - Connection-level congestion control - Integrated TLS 1.3 with single handshake - Connection migration support via connection identifiers - Reduced latency with 0-RTT data transmission
HTTP/3 maps HTTP semantics onto QUIC streams, inheriting these transport-layer improvements while maintaining HTTP/2's design principles.
HTTP/3 Protocol Architecture
Transport Layer
HTTP/3 operates exclusively over QUIC (RFC 9000), utilizing QUIC's stream multiplexing and flow control mechanisms. Each HTTP request/response pair maps to a single bidirectional QUIC stream, providing stream-level isolation and independent delivery guarantees.
Frame Structure
HTTP/3 communication uses typed frames transmitted within QUIC streams. Common frame types include:
- HEADERS: Carries HTTP header fields (compressed using QPACK)
- DATA: Conveys request or response payload
- SETTINGS: Communicates connection-level parameters
- PUSH_PROMISE: Initiates server push
- GOAWAY: Initiates graceful connection shutdown
Frame types are variable-length encoded, with the frame type and length fields preceding the payload.
Stream Types
HTTP/3 defines three stream types:
- Request streams (client-initiated bidirectional): Carry HTTP request/response exchanges
- Control stream (unidirectional): Manages connection-wide settings and parameters
- Push streams (server-initiated unidirectional): Deliver server-pushed responses
Request/Response Model
Each HTTP request/response cycle consumes one client-initiated bidirectional QUIC stream. The client sends HEADERS and optional DATA frames, then half-closes the stream. The server responds with HEADERS and DATA frames before closing its sending side.
Stream independence ensures that packet loss on one stream does not block others, eliminating TCP-layer head-of-line blocking.
Server Push
HTTP/3 supports server push through the PUSH_PROMISE frame, which reserves a push stream identifier. The server then sends the pushed response on the corresponding push stream. Clients can limit or disable push using MAX_PUSH_ID and CANCEL_PUSH frames.
Header Compression with QPACK
HTTP/3 replaces HTTP/2's HPACK compression with QPACK (RFC 9204), designed to handle QUIC's unordered stream delivery. QPACK maintains compression efficiency while allowing headers to be decoded independently when streams arrive out of order.
QPACK features: - Dynamic table updates on a dedicated unidirectional stream - Reference tracking to prevent decoding dependencies - Configurable risk/compression tradeoff - Backward compatibility with HPACK concepts
Header Format Examples
HTTP/1.1 Header Format
GET /index.html HTTP/1.1
Host: example.com
User-Agent: Mozilla/5.0
Accept: text/html,application/xhtml+xml
Accept-Encoding: gzip, deflate
Connection: keep-alive
HTTP/1.1 uses plain-text headers with CRLF delimiters. Each header field is a name-value pair separated by a colon.
HTTP/2 Header Format
HEADERS Frame (Stream 1):
:method = GET
:path = /index.html
:scheme = https
:authority = example.com
user-agent = Mozilla/5.0
accept = text/html,application/xhtml+xml
accept-encoding = gzip, deflate
HTTP/2 introduces pseudo-header fields (prefixed with :) for request metadata. Headers are encoded using HPACK and transmitted in a HEADERS frame.
HTTP/3 Header Format
HEADERS Frame (Stream 0):
:method = GET
:path = /index.html
:scheme = https
:authority = example.com
user-agent = Mozilla/5.0
accept = text/html,application/xhtml+xml
accept-encoding = gzip, deflate
HTTP/3 maintains HTTP/2's pseudo-header syntax but uses QPACK encoding instead of HPACK. The semantic meaning and structure are identical to HTTP/2.
HTTP/2 vs HTTP/3 Comparison
| Feature | HTTP/2 | HTTP/3 |
|---|---|---|
| Transport Protocol | TCP | QUIC (over UDP) |
| Connection Establishment | Separate TCP and TLS handshakes (2-3 RTT) | Combined QUIC+TLS handshake (1-RTT) |
| Header Compression | HPACK | QPACK |
| Stream Multiplexing | Application layer (within TCP connection) | Transport layer (native QUIC streams) |
| Head-of-Line Blocking | TCP-layer blocking affects all streams | Per-stream delivery (no cross-stream HoL) |
| Connection Migration | Not supported (TCP 4-tuple bound) | Supported via connection IDs |
| 0-RTT Support | Limited (TLS 1.3 early data with constraints) | Native 0-RTT with replay protection |
| Header Field Syntax | Pseudo-headers (:method, :path, :scheme) |
Same as HTTP/2 |
| Server Push | PUSH_PROMISE frame | PUSH_PROMISE frame (same semantics) |
| Flow Control | Stream and connection level | Stream and connection level |
HTTP/3 Implementation in Spooky
Spooky implements HTTP/3 termination at the edge, accepting HTTP/3 client connections and translating them to HTTP/2 for backend forwarding. This approach enables HTTP/3 client support without requiring backend infrastructure changes.
Protocol Conversion
The Spooky bridge component handles bidirectional translation between HTTP/3 and HTTP/2:
-
Request path: HTTP/3 HEADERS and DATA frames are parsed, decompressed via QPACK, and re-encoded as HTTP/2 frames with HPACK compression for backend transmission.
-
Response path: HTTP/2 responses from backends are decoded, headers are converted to QPACK format, and frames are transmitted over the client's HTTP/3 stream.
Stream Mapping
Each HTTP/3 client stream maps to a corresponding HTTP/2 stream on a backend connection. Stream lifecycle events (creation, data transfer, closure) are synchronized between protocols.
Connection Management
Spooky maintains separate connection pools for client-facing HTTP/3 sessions and backend HTTP/2 connections. QUIC connection state is managed by the edge component, while HTTP/2 connection pooling is handled by the transport layer.
Feature Support
- Header compression: Full QPACK support for clients, HPACK for backends
- Flow control: QUIC stream and connection flow control enforced
- Server push: Not currently implemented (client-to-proxy only)
- Priority signaling: HTTP/3 priority frames are mapped to HTTP/2 priority when supported by backends
Performance Characteristics
HTTP/3 offers several performance advantages over HTTP/2:
Reduced latency: Combined QUIC+TLS handshake reduces connection establishment time. 0-RTT resumption enables immediate data transmission for repeat connections.
Improved loss resilience: Independent stream delivery prevents packet loss on one stream from blocking others. TCP's retransmission delays do not propagate across streams.
Better mobile performance: Connection migration allows QUIC connections to survive network changes (Wi-Fi to cellular transitions) without interruption.
Optimal congestion control: QUIC's congestion control operates at the connection level without TCP's limitations, enabling more accurate RTT estimation and loss detection.
References
- RFC 9114: HTTP/3
- RFC 9000: QUIC Transport Protocol
- RFC 9204: QPACK Header Compression
- RFC 9218: Extensible Prioritization Scheme for HTTP