Ten years ago I wrote about Google’s QUIC protocol , back when it was an experiment you could realistically only test against Google’s own servers. I was excited about it, and I ended that post hoping the spec would get standardised and show up in other browsers and servers.
It did. QUIC is an IETF standard now, it’s the foundation of HTTP/3, and it runs a large share of the web. But the protocol that shipped isn’t the one I described in 2016. If your mental model of QUIC is still “Google’s thing with its own crypto and forward error correction”, it’s a decade out of date. Here’s what changed.
From gQUIC to IETF QUIC#
The version I described in 2016 (now called gQUIC, Google’s QUIC) had its own homegrown crypto layer. That’s the single biggest change. IETF QUIC dropped Google’s crypto entirely and uses TLS 1.3 for the handshake instead, defined in RFC 9001 . QUIC doesn’t replace TLS, it embeds it.
The other big shift is structural. Where gQUIC was one blob doing transport and HTTP together, IETF QUIC split into clean layers, each its own RFC:
- RFC 9000 : the QUIC transport itself (streams, connections, framing).
- RFC 9001 : how TLS 1.3 secures it.
- RFC 9002 : loss detection and congestion control.
- RFC 9114 : HTTP/3, the mapping of HTTP onto QUIC.
- RFC 9204 : QPACK, the header compression (HTTP/2’s HPACK breaks when streams can arrive out of order).
The transport RFCs landed in May 2021, HTTP/3 and QPACK in June 2022. So “HTTP/3” is specifically HTTP running over QUIC. QUIC is the transport; HTTP/3 is one thing you run on top of it.
In 2016 I described QUIC as replacing “the TLS stack and parts of HTTP/2”. That shape held up; the naming just settled. The HTTP part is HTTP/3, and the crypto part is standard TLS 1.3 instead of a Google-bespoke layer.
What got dropped, and what stayed#
The thing I spent the most words on in 2016 didn’t survive: Forward Error Correction. The idea was elegant, ship redundant data so a lost packet could be reconstructed without a retransmit, RAID 5 for the network. In practice Google’s XOR-based scheme hurt more than it helped (it measurably degraded YouTube performance) and it was removed before standardisation. It never made it into the IETF spec. If you read my old post and got excited about FEC, sorry, that one’s gone.
What stayed is the more important part:
- No head-of-line blocking. Still the headline feature. Independent streams over UDP mean a lost packet for one resource doesn’t stall the others, unlike a single TCP connection where order matters.
- Connection migration. The Connection ID I called the “Connection UUID” in 2016 is real and standardised. You can move from WiFi to cellular and keep the same QUIC connection, no renegotiation.
- Fast handshakes. The 0-RTT / 1-RTT connection setup that was the whole point. Against a known server, application data can go out in the first flight.
So the broad strokes from 2016 survived. The experimental bits, FEC and Google’s crypto, are what got replaced.
It’s not experimental anymore#
In 2016 the only server you could run QUIC on was Caddy, and it was experimental on both ends. That’s the part that’s most different in 2026: HTTP/3 is finished and boring now, and it runs nearly everywhere.
- nginx ships it since 1.25.0. I wrote up serving HTTP/2 and HTTP/3 with nginx separately.
- Caddy has it on by default since 2.6, no flags.
- LiteSpeed and Cloudflare’s edge serve it at scale.
- Every major browser speaks it.
Browsers don’t reach for HTTP/3 out of nowhere, though. They learn a site supports it from the Alt-Svc header on a normal HTTPS (HTTP/2) response. Here’s Google advertising it:
$ curl -I --http2 https://www.google.com/ | grep -i alt-svc
alt-svc: h3=":443"; ma=2592000,h3-29=":443"; ma=2592000
That h3=":443" tells the browser “I also speak HTTP/3 on UDP 443, remember it for ma seconds”. The next request goes out over h3. The h3-29 you sometimes still see is the old draft-29 alias, kept around for older clients.
Verify h3 is negotiating#
curl speaks HTTP/3 directly now, which is the easiest check. In 2016 I wrote that I hoped curl would implement QUIC “soon”. It did. A build with HTTP/3 support gives you --http3:
$ curl --http3 -I https://www.cloudflare.com/
HTTP/3 200
date: Sat, 06 Jun 2026 19:04:50 GMT
content-type: text/html; charset=utf-8
...
That HTTP/3 200 on the status line is the proof. Your distro’s stock curl may or may not be built with HTTP/3, so check curl --version for HTTP3 in the features line first. If it’s missing, a few distros and the official curl Docker images ship an HTTP/3-enabled build.
I tested this both ways while writing the post. Against www.cloudflare.com above, and against a local nginx 1.31.1 container serving HTTP/3, which answered:
$ curl --http3 -k -I https://h3server/
HTTP/3 200
server: nginx/1.31.1
date: Sat, 06 Jun 2026 19:02:13 GMT
content-type: text/plain
content-length: 20
alt-svc: h3=":443"; ma=86400
In the browser: open DevTools, the Network tab, enable the Protocol column, and HTTP/3 requests show as h3. The first request after a cold load is usually h2, because the browser only learns about h3 from that first Alt-Svc header.
Debugging when it doesn’t#
QUIC is encrypted end to end, including most of its transport headers, so you can’t point Wireshark at it and read the stream the way you could with plaintext TCP. The tooling is different.
In Chrome, chrome://net-internals/#quic is long gone. You capture a log with chrome://net-export/ and load it into the NetLog viewer
to inspect QUIC sessions and per-connection detail.
For deeper protocol-level work there’s qlog, a structured QUIC logging format, and qvis , a set of visualizations that take qlog (or a Chrome netlog) and draw the handshake, congestion window, and stream multiplexing for you. It’s what the QUIC community uses to chase down real bugs.
The firewall reality, still#
One thing hasn’t changed since 2016: HTTP/3 is UDP, and most firewalls only allow TCP/443. I made a whole section out of this in the old post, half-joking that getting UDP/443 past enterprise security sounds fishy. Jim Roskind, who designed QUIC, left a comment predicting usability would win and UDP/443 would get opened. He was right.
On your own servers it’s still the thing people forget. Open 443/udp, inbound on servers and outbound on clients. If you forget, nothing visibly breaks, and that’s the trap: the client silently falls back to HTTP/2 over TCP and you’ll think h3 is working when it never negotiates. Check the firewall first.
Where it landed#
In 2016 I wrote that I couldn’t wait to see the QUIC spec become final and land in other browsers and servers. Ten years later it has: QUIC is RFC 9000, HTTP/3 is RFC 9114, and both are on by default across most of the web. The only thing the old post got wrong was FEC, and the protocol is better without it.