Free — no signup required

HTTP/3: Solving the TCP Problem

3 min read

The New Bottleneck: Transport-Level Head-of-Line Blocking

HTTP/2 fixed application-level head-of-line blocking — one slow request no longer blocks others at the HTTP layer. But it exposed a deeper problem: TCP itself causes head-of-line blocking at the transport layer.

TCP guarantees reliable, ordered delivery. Every byte sent must be acknowledged by the receiver. If a packet is lost in transit, TCP stops delivering any subsequent data to the application until that specific packet is retransmitted and received. It doesn't matter that the lost packet belonged to stream 3 and streams 1, 2, 4, and 5 are completely unaffected — TCP sees one byte stream, and it halts everything.

On a reliable fiber connection, packet loss is rare (< 0.1%) and this barely matters. On a mobile network or public Wi-Fi, packet loss rates of 1-5% are common. At 2% packet loss with 100 streams multiplexed over HTTP/2, statistically almost every round-trip will hit a lost packet, and the entire connection stalls each time. HTTP/2 can actually perform worse than HTTP/1.1 in high-loss environments because HTTP/1.1's multiple connections mean a loss on one connection doesn't affect the others.

Enter HTTP/3 and QUIC

HTTP/3, standardized in 2022 (RFC 9114), solves TCP head-of-line blocking by replacing TCP entirely with QUIC — a transport protocol originally developed by Google and now an IETF standard (RFC 9000).

QUIC runs over UDP (User Datagram Protocol). UDP is the opposite of TCP: it sends packets with no delivery guarantees, no ordering, and no acknowledgment. This sounds like a step backward, but it's actually the foundation for building something better.

QUIC reimplements the reliability and ordering guarantees of TCP, but does so per stream rather than for the entire connection. Each QUIC stream has its own flow control and retransmission logic. If a packet carrying data for stream 3 is lost, only stream 3 pauses to wait for retransmission. Streams 1, 2, 4, and 5 continue delivering data to the application without interruption.

QUIC also provides two other major improvements:

1. Faster Connection Setup

TCP requires a 3-way handshake before any data can flow. TLS (encryption) adds another 1-2 round trips on top. Total: 2-3 round trips before the first byte of application data.

QUIC combines the transport and cryptographic handshakes. A new QUIC connection requires only 1 round trip before data flows. For repeat connections to the same server, QUIC supports 0-RTT (zero round-trip time) resumption — the client can send application data in the very first packet using cached session parameters.

2. Connection Migration

TCP connections are identified by a 4-tuple: source IP, source port, destination IP, destination port. When you switch from Wi-Fi to cellular on your phone, your IP address changes, and every TCP connection breaks. You experience this as apps stalling and reconnecting.

QUIC connections are identified by a Connection ID — an opaque identifier chosen by the endpoints, independent of IP addresses. When your phone switches networks, the QUIC connection survives. The client sends the next packet from its new IP, and the server recognizes the Connection ID and continues seamlessly. This is called connection migration and is a significant improvement for mobile users.

Interview Tip

A common interview question: "If QUIC is built on UDP, which is unreliable, how is HTTP/3 reliable?" The answer: QUIC implements its own reliability layer on top of UDP in user space. It handles packet acknowledgment, retransmission, and ordering per-stream. The difference from TCP is that this reliability is stream-scoped, not connection-scoped, eliminating transport-level HOL blocking. Follow-up: QUIC also mandates TLS 1.3 — there is no unencrypted QUIC. Encryption is not optional.

This is one of 18 chapters

Every chapter is free — Kubernetes, Terraform, SRE, distributed systems, and more — with fast daily review built in.

Sign up free