Spent a weekend with the QUIC RFCs (9000/9001). Short version of why putting HTTP on UDP made sense.
Head-of-line blocking
HTTP/2 multiplexes streams over one TCP connection, but TCP delivers bytes strictly in order — one lost segment stalls every stream sharing that connection. QUIC moves the streams below the reliability layer, so a loss on stream A doesn’t block stream B. That’s the entire pitch, and it matters most on lossy mobile links.
The handshake is folded in
// 1-RTT: the TLS 1.3 handshake rides inside QUIC CRYPTO frames
// 0-RTT: resume with cached transport params + a PSK
// -> app data in the first flight (replayable; idempotent only)
Connection IDs
A QUIC connection is keyed on a connection ID, not the 4-tuple. So it survives a NAT rebind or a Wi-Fi → cellular switch without tearing down — the same session ID just shows up from a new address. TCP can’t do that.
The cost
Almost everything past the header is encrypted, including most of the handshake. Great for privacy, mildly painful for debugging — tcpdump shows you opaque UDP and you end up living in qlog. And because it’s userspace on most stacks, you trade kernel TCP’s maturity for flexibility.