Why does QUIC exist when TCP already works?
TCP works fine — until you're on a flaky phone connection, juggling a dozen multiplexed streams, and one lost packet stalls all of them. QUIC is the protocol designed around that specific frustration.
Why it exists
Picture this: you’re on a video call walking out of your house. Your phone hops from home Wi-Fi to mobile data. With most older internet protocols the call would drop right there — your phone’s “address” just changed, and the connection is defined by that address. With newer ones, the call survives the switch without a hiccup. That’s QUIC at work. Same goes for the moment a single packet gets lost on a flaky hotel Wi-Fi: with TCP every other download in your browser briefly freezes too. QUIC was designed so only the affected file pauses.
For decades, the answer to “how do two computers reliably exchange a stream of bytes over the internet?” has been TCP. It works. It’s everywhere. So why did Google spend years inventing a replacement and pushing it through the IETF?
Because TCP was designed in a world that no longer exists. Three things changed underneath it, and the friction kept growing:
- Connections move now. Your phone hops between Wi-Fi and cellular mid-page-load.
A TCP connection is keyed by
(source IP, source port, dest IP, dest port)— change any of those four and the connection is, by definition, dead. - Pages need many things at once. A modern page pulls dozens of resources in parallel. HTTP/2 tried to fix this by multiplexing many streams over a single TCP connection. But TCP is a single ordered byte stream — if one packet is lost, every stream above it has to wait. This is head-of-line blocking, and HTTP/2 made it worse, not better, on lossy links.
- Encryption is the default. TLS used to be optional. Now it’s mandatory for anything serious. But TLS sits on top of TCP, so connecting takes a TCP handshake (one round trip) plus a TLS handshake (one or two more). On a satellite link or congested mobile, that’s painful before any actual data moves.
You could fix all of this inside TCP, in theory. In practice you can’t, because TCP lives in the kernel and middleboxes — routers, NATs, “smart” firewalls — have spent thirty years hard-coding assumptions about what TCP packets look like. Try to add a new TCP option and a chunk of the internet’s middle silently drops your packets. This is protocol ossification: the protocol can’t change because the network refuses to let it.
QUIC’s move is to side-step that entirely. Build a new transport on top of UDP, encrypt everything (including the parts middleboxes try to inspect), and put the protocol in userspace so applications can ship updates without waiting for the kernel.
Why it matters now
If you serve traffic to browsers, you’re already using QUIC for a chunk of it. HTTP/3 is HTTP carried over QUIC, and the major browsers and CDNs negotiate it by default when both sides support it. Your phone’s first connection to a popular site this morning probably went over QUIC and you didn’t notice — which is the whole point.
For engineers, the practical consequences:
- Faster connection setup. QUIC bundles the transport handshake and the cryptographic handshake into one. First-time connections take roughly one round trip; resumed connections can take zero round trips for the first request bytes (so-called 0-RTT).
- Per-stream loss recovery. If one stream loses a packet, the others keep flowing. HTTP/3 finally gets the multiplexing HTTP/2 promised.
- Connection migration. A QUIC connection has its own ID, decoupled from IP and port. Your laptop closing the lid and reopening on a new network can, in principle, keep the same connection alive.
- Operationally different. QUIC traffic is opaque to most middleboxes,
which means a lot of “we look at TCP windows” tooling no longer works.
Debugging shifts toward endpoint logs and
qlogtraces.
The short answer
QUIC = UDP + TLS 1.3 + per-stream reliability + connection IDs
QUIC is a reliable, multiplexed, encrypted transport built on UDP instead of TCP. It folds the crypto handshake into the transport handshake, gives each logical stream its own loss recovery so a dropped packet doesn’t stall its neighbors, and identifies connections by an ID rather than the source/destination 4-tuple — so the connection survives when the network path underneath changes.
How it works
Three design moves do most of the work.
1. UDP as the substrate. QUIC packets ride inside UDP datagrams. UDP gives you almost nothing — just “deliver this to that IP/port, maybe” — and that’s exactly the appeal. There’s so little structure for middleboxes to ossify against. The protocol logic that TCP does in the kernel (sequence numbers, acknowledgments, congestion control, retransmission) all moves into a QUIC library in userspace.
2. Encryption is part of the transport, not a layer above it. In TCP+TLS the transport runs first, then TLS negotiates on top. In QUIC, almost every byte of every packet is encrypted or authenticated from the start, including fields a middlebox would historically read. The handshake reuses TLS 1.3’s key schedule but folds it into the transport’s own packets. The result is one unified handshake instead of two.
This is also a deliberate anti-ossification move. If middleboxes can’t read the fields, they can’t grow assumptions about them, and the protocol stays free to evolve.
3. Streams are first-class, and independent. A QUIC connection carries many streams. Each has its own sequence space and its own retransmission state. Lose a packet on stream 7 and only stream 7 is held up; streams 1–6 and 8–N keep delivering bytes to the application. This is the head-of-line blocking fix, and it’s the part HTTP/2 fundamentally couldn’t do because TCP underneath only knew about one stream.
Connection IDs. Instead of (srcIP, srcPort, dstIP, dstPort), a QUIC
connection is identified by an opaque connection ID chosen during the
handshake. If your IP changes — Wi-Fi to LTE, NAT rebinding — the connection
ID is still valid, and after a small “is this really you?” check the
connection continues. TCP fundamentally can’t do this without protocol
surgery.
Show the seams
A few things the marketing version glosses over:
- QUIC isn’t free. Doing transport in userspace and encrypting every packet costs CPU. Early deployments saw meaningfully higher per-byte CPU cost than TCP+TLS, and a lot of subsequent work (kernel offloads, GSO/GRO for UDP, hardware crypto) has been about closing that gap. I don’t have a current number to pin here that I’d defend — measurements depend heavily on kernel version, NIC, and library — but “free upgrade” it isn’t.
- 0-RTT is a security tradeoff. Data sent in the zero-round-trip first flight can be replayed by an attacker who captured the packets, so it’s only safe for idempotent operations. This is a real footgun if an application doesn’t think about it.
- Some networks block or rate-limit UDP. Corporate networks especially. Browsers handle this by racing QUIC against TCP and falling back, but if you’re building a non-browser client you have to plan for this.
- The “0 round trips on resumption” claim has caveats. It assumes a recent prior connection and acceptable security properties for the data. Cold connections still pay one round trip.
- “Google invented it” is shorthand. Google shipped the original gQUIC inside Chrome and their servers, and that work fed into the IETF standardization process that produced the version specified in RFC 9000. The deployed-on-the-internet QUIC today is the IETF version, not the original gQUIC, and they’re not wire-compatible.
Famous related terms
- HTTP/3 —
HTTP/3 = HTTP semantics + QUIC— same HTTP you know, carried over QUIC instead of TCP+TLS. - TCP —
TCP = reliable + ordered + single byte stream— the protocol QUIC is replacing for browser traffic, still the right tool for many other workloads. - TLS 1.3 —
TLS 1.3 ≈ "the fast modern handshake"— QUIC reuses its key exchange. - Head-of-line blocking —
HoL blocking ≈ "one slow car blocks the whole lane"— the specific failure mode QUIC’s per-stream design fixes. - Protocol ossification —
ossification ≈ "you can't change it because the middle of the network won't let you"— the structural reason a TCP successor had to be built on UDP.
Going deeper
- RFC 9000 — the QUIC transport specification. Drier than the blog posts but the actual normative source.
- RFC 9001 — how TLS 1.3 is folded into QUIC. Worth reading once just to see how unified the handshake really is.
- Google’s “The QUIC Transport Protocol” paper (SIGCOMM 2017) — the design and measurements from the gQUIC era; useful for the why, even though the wire format has since changed.
qlogandqvis— endpoint logging format and visualizer for debugging QUIC connections, which is where you end up oncetcpdumpstops being enough.