The Real Reason HTTP/3 Exists

HTTP/3 has been in development for nearly five years, and while earlier versions were available experimentally, wider adoption is expected to accelerate. The common story you'll hear is that HTTP/3 is dramatically faster than HTTP/2, with lower latency and better parallelism. The reality is more nuanced: HTTP/3 is an evolution, not a revolution, and its performance benefits will be significant for some users but modest for most.

To understand why HTTP/3 exists at all, it helps to look at the protocol stack. When you use HTTPS, several protocols work together: HTTP handles URLs and data interpretation, TLS provides encryption, TCP ensures reliable delivery by retransmitting lost packets, and IP routes packets across the network. This layering lets higher-level protocols reuse the work of lower ones — HTTP doesn't need to implement encryption because TLS already does it.

The problem is that TCP, which has been a cornerstone of the web since its early days, wasn't designed for maximum efficiency. Its age is showing in ways that directly affect web performance:

  • Connection setup costs a full round trip. The TCP handshake ensures both endpoints exist and can exchange data, but on geographically distant connections, each round-trip time can exceed 100 milliseconds. Nothing else can happen on that connection until the handshake completes.
  • Head-of-line blocking. TCP treats all transmitted data as a single byte stream, even when transferring multiple files simultaneously. If packets for one resource are lost, every other resource on that connection is delayed while the lost data is recovered.

These inefficiencies are manageable — TCP has worked for over 30 years — but they visibly affect HTTP. Efforts to upgrade TCP itself, such as TCP Fast Open to eliminate handshake overhead or MultiPath TCP to use Wi-Fi and cellular connections simultaneously, have largely stalled. The barrier isn't technical difficulty; it's deployment.

TCP is implemented in nearly every internet-connected device, including the middleboxes that sit between clients and servers: firewalls, load balancers, routers, caching servers, and proxies. These devices are harder to update and often strict about what they accept. Many active middleboxes make assumptions about TCP that extensions break, so new features can't be used at scale until enough of these devices are updated — a process that can take a decade or more. TCP has become practically impossible to evolve.

That realization in the early 2010s led to a two-phase plan. First, focus on fixing HTTP/1.1, which became HTTP/2. Second, build a replacement for TCP from scratch. That replacement is QUIC, and it differs from TCP in several fundamental ways that make it unsuitable to run HTTP/2 directly on top of it. So HTTP/2 was adapted in key areas to work with QUIC, and that adapted version became HTTP/3.

On Protocol Stacks

HTTP/3 users are really relying on several protocols at once. HTTP itself deals with URLs and data interpretation; TLS 1.3 handles encryption; QUIC provides reliable transport with features like packet retransmission or connection migration; and IP routes packets across networks, including through middleboxes. Each layer has its own responsibilities — and its own potential bottlenecks.

The naming is partly marketing: "HTTP/3" is clearer than "HTTP/2-over-QUIC." But the naming also reflects reality — the differences between HTTP/1.1 and HTTP/2 are much larger than those between HTTP/2 and HTTP/3. Most of what people get excited about with HTTP/3, including faster connection setup, less head-of-line blocking, and connection migration, actually comes from the QUIC transport layer. HTTP/3 itself is the relatively small adaptation needed to make HTTP run over QUIC.

The key point for developers deploying or evaluating the protocol: what we really needed was a new transport protocol, and HTTP/3 is the version of HTTP that can use it.

Why QUIC Isn’t Just “TCP Over UDP”

It’s tempting to simplify the HTTP/3 story into a clean performance narrative: TCP is old and slow, UDP is new and fast, so HTTP/3 runs on UDP and wins. That framing is wrong, and it obscures what QUIC actually is. QUIC is not a lightweight UDP wrapper; it is a full transport protocol that reimplements TCP’s reliability and congestion machinery with modern improvements.

Understanding this distinction matters because QUIC is generic. Like TCP, it can carry many protocols beyond HTTP—DNS, SSH, SMB, RTP, and others already run or are being built to run over QUIC. So the transport layer deserves attention on its own terms, not just as a footnote to HTTP/3.

The UDP Convenience, Not the UDP Performance

The reason QUIC sits on top of the User Datagram Protocol (UDP) is almost entirely pragmatic. In an ideal world, QUIC would be an independent transport protocol running directly on IP. But introducing a brand-new protocol to the Internet stack would require every intermediary device on the path to be updated to recognize and forward it. That is precisely the problem that has made TCP evolution so slow.

UDP is the only other broadly supported transport-layer protocol on the Internet, which makes it a convenient carrier. The protocol itself is as minimal as a transport can be: it provides port numbers (80 for HTTP, 443 for HTTPS, 53 for DNS) but nothing else. There is no connection setup, no acknowledgement, and no retransmission of lost packets. Its “best effort” behavior means no handshake wait and no head-of-line blocking. That is why it suits live video conferencing and gaming (where stale data is useless) and low-latency lookups like DNS, which should complete in a single round trip.

But HTTP/3’s decision to use UDP has nothing to do with inheriting those characteristics. QUIC reimplements all of TCP’s guarantees on top of the bare UDP socket: it is reliable, it acknowledges received packets, retransmits lost ones, performs a cryptographic and transport handshake, and enforces flow-control and congestion-control limits on senders. The claim that HTTP/3 is faster because it skips connection setup or tolerates packet loss like raw UDP is simply incorrect.

UDP’s only real contribution here is deployment feasibility. Because the Internet already speaks UDP, QUIC can be introduced without a global hardware or firmware upgrade cycle.

The genuine advantage QUIC brings is that it implements those TCP-like features more intelligently, drawing on decades of deployment experience with TCP while adding core innovations we are still exploring in this article.

What QUIC Actually Changes

The “free lunch” reading of HTTP/3 does not hold up. Performance gains come from a redesigned transport, not from discarding transport-level rigor. QUIC layers a sophisticated, modernized version of TCP on UDP, precisely so that this improved transport can be deployed broadly without waiting for the rest of the Internet to change.

What Actually Changes With QUIC

QUIC’s headline improvements over TCP — 0-RTT connection establishment, connection migration, and better resilience on lossy networks — all trace back to four foundational design decisions:

  1. TLS is mandatory and built directly into the transport layer.
  2. Multiple independent byte streams are a first-class concept.
  3. Connections are identified by connection IDs, not just network addresses.
  4. The protocol is frame-based and designed for extensibility.

Encryption Is Not Optional Anymore

TLS was historically a separate, optional layer layered on top of TCP. That separation is why we still distinguish between plaintext HTTP and encrypted HTTPS. Over time, the industry moved to a “secure by default” posture; no major browser even supports the cleartext HTTP/2 mode that the RFC technically defines.

QUIC takes that evolution to its logical end. There is no cleartext QUIC. Standardized QUIC embeds TLS 1.3 directly into the protocol, rather than running it as a separate layer. Practically, QUIC encapsulates the TLS handshake, then takes over packet encryption itself. Even most of the QUIC packet header is encrypted; transport metadata like packet numbers, which TCP sends in the clear, is hidden from intermediaries.

Comparison of TLS over TCP and QUIC
TLS, TCP, and QUIC handshake durations (Large preview)

This approach has three main payoffs. First, it is more secure: attackers get no cleartext fallback to exploit. Second, it saves a round trip: the transport and cryptographic handshakes happen together instead of sequentially. Third, it makes the protocol easier to evolve, since middleboxes can no longer inspect and accidentally break on internal details they don’t understand.

The trade-offs are real, though. Networks that rely on inspecting TCP metadata for troubleshooting or filtering may block QUIC. Per-packet encryption also adds processing overhead compared to TLS-over-TCP, which can encrypt multiple packets in one operation. And while QUIC’s complexity means only well-resourced organizations will deploy it optimally, the notion that QUIC itself centralizes the web is overstated: the protocol exposes no more user-level information to observers than TLS-over-TCP does.

QUIC deep packet encryption
Unlike TCP + TLS, QUIC also encrypts its transport-layer meta data in the packet header and payload. (Note: field sizes not to scale.) (Large preview)

The takeaway: QUIC is encrypted by design, not by configuration. That improves security and evolvability at the cost of some processing overhead.

Streams Are Independent At The Transport Layer

A web page is really a collection of independent binary resources — HTML, CSS, JavaScript, images — each broken into roughly 1,400-byte packets and streamed over the network as its own byte stream.

HTTP/1.1 gave each resource its own TCP connection, with browsers capping concurrent connections (typically 6–30 per page). HTTP/2 improved on this by multiplexing all resources onto a single TCP connection, interleaving packets from different streams: instead of AAAA, BBBB, CCCC on separate connections, one connection carries something like AABBCCAABBCC.

HTTP/1 versus HTTP/2 and HTTP/3 multiplexing
HTTP/1.1 does not allow multiplexing, unlike both HTTP/2 and HTTP/3. (Large preview)

The problem: TCP doesn’t know anything about A, B, or C. It treats all incoming data as a single stream, X. If a packet carrying stream B’s data is lost, TCP holds back all subsequent data — including stream A and C packets that arrived fine — until the hole is filled. This is head-of-line (HoL) blocking, and it makes multiplexing over TCP slower than it should be.

QUIC solves this by making multiple independent streams a core transport-layer concept. Packet loss detection and recovery happen per stream. If stream B loses a packet, QUIC only stalls stream B; streams A and C continue delivering data to the application immediately.

Head-of-line blocking in HTTP/1.1, 2, and 3
QUIC allows HTTP/3 to bypass the head-of-line blocking problem. (Large preview)

This is also why HTTP/3 can’t simply be HTTP/2 running over QUIC. HTTP/2 has its own stream abstraction on top of TCP; layering it on QUIC would create two competing stream mechanisms. Instead, HTTP/3 removes HTTP-level stream logic and reuses QUIC streams directly.

The takeaway: TCP was never designed for multiplexing independent files. QUIC makes independent streams intrinsic to the transport layer, eliminating a class of HoL blocking that HTTP/2 over TCP can’t avoid.

Connections Survive Network Changes

A TCP connection is uniquely identified by a 4-tuple: client IP, client port, server IP, server port. Change any one of those, and the connection is dead.

Consider a smartphone on Wi-Fi moving to cellular. The phone gets a new IP address on the new network. The server sees packets from an unfamiliar IP and cannot distinguish them from a brand-new connection — TCP has no mechanism for the client to say “I changed addresses, but this is the same connection.” The result: the old connection is unusable, a new handshake is required, and any in-progress download or video call has to restart or black out.

Parking-lot problem
The parking-lot problem with TCP: Once the client gets a new IP, the server can no longer link it to the connection. (Large preview)

QUIC introduces the connection identifier (CID) to break this dependency. A CID is a transport-level identifier carried in every QUIC packet, and — crucially — unlike IP addresses and ports, it does not change when the client switches networks.

QUIC uses connection IDs to allow persistent connections
QUIC uses connection identifiers (CIDs) to allow connections to survive a network change. (Large preview)

This enables connection migration: endpoints recognize a connection by its CID, not by the 4-tuple. No new handshake is needed after a network change, and state, like an ongoing download, remains intact.

Of course, a single static CID would let third parties track users as they move between networks. QUIC avoids that by rotating CIDs. Client and server agree on a shared list of CIDs, all mapping to the same logical connection. The client tags packets with one CID on Wi-Fi, then switches to another on cellular. Because the mapping list is negotiated in encrypted QUIC traffic, observers can’t link the two.

QUIC uses multiple connection IDs for privacy reasons
QUIC uses multiple negotiated connection identifiers (CIDs) to prevent user tracking. (Large preview)

The takeaway: TCP connections break when any part of the 4-tuple changes. QUIC adds an independent connection ID, making connections resilient to network changes like Wi-Fi-to-cellular handoffs.

A Protocol Designed To Change

QUIC is built for evolution in several ways. Because its payload and most of its header are encrypted, new protocol versions only require updates to endpoints, not to every middlebox in the path that was written for an older TCP format.

Instead of a monolithic fixed packet header, QUIC uses short packet headers plus a set of frames inside the payload to carry metadata.

There are frames for acknowledgements (ACK), for connection migration support (NEW_CONNECTION_ID), and for data itself (STREAM), among others. This is partly an efficiency measure — packets only carry the metadata they actually need — but it also makes the protocol extensible: new frame types can be defined without redesigning the header. The proposed DATAGRAM frame, for sending unreliable data over QUIC, is one such extension.

Unlike TCP, QUIC uses framing to carry meta data
QUIC uses individual frames to send meta data, instead of a large fixed packet header. (Large preview)

Negotiation also happens through transport parameters carried in a custom TLS extension. These parameters let endpoints configure per-connection behavior — enabling features like connection migration, declaring extension support, and setting flow control limits — and the standard explicitly allows new parameters to be defined.

Finally, QUIC implementations mostly live in user space, unlike TCP’s typical kernel-space implementation. That makes experimentation and deployment of new implementations and extensions substantially easier.

The takeaway: QUIC is effectively version 1 of a protocol explicitly intended to iterate quickly, with extension mechanisms built in at every layer.

Wrapping Up: What QUIC Actually Changes

Stepping back, the central story of HTTP/3 is not really about HTTP at all. It is about TCP, a protocol designed long before the modern web's demands existed. TCP is everywhere, but that ubiquity is also its weakness: nearly every networked device ships its own TCP implementation, making any meaningful evolution of the protocol painfully slow to roll out.

QUIC sidesteps that deployment problem by running over UDP, which virtually all network hardware already supports. In essence, QUIC is TCP 2.0, rebuilt with forward compatibility in mind. It is encrypted by default and uses a flexible framing mechanism, so future improvements do not require replacing firmware across the internet.

Beyond that, QUIC largely mirrors familiar TCP mechanics: the handshake, reliability guarantees, and congestion control all carry over. The genuinely new pieces are its handling of multiple byte streams and the connection ID. Those two additions are precisely why HTTP/2 could not simply run on top of QUIC; the mapping required a new protocol, which became HTTP/3 — effectively HTTP/2 carried over QUIC.

The practical payoff is a set of performance opportunities, though they are more subtle than most introductory articles suggest. Head-of-line blocking, connection migration, and handshake latency all improve, but the real-world gains depend heavily on context. Now that the core concepts are in place, those nuances are worth examining in detail.

Series Navigation

Further Reading

(vf, il, al, mrn)