Skip to content
Hogin Hogin
Go back

HTTP/3 and QUIC Explained Simply

6 мин чтения

HTTP/3 is the third major version of the protocol the whole web runs on. The big change isn’t new headers — it’s a new foundation: the transport moved from TCP to UDP, and on top of it runs a new protocol called QUIC. Let’s see why, how it beats the older versions, and what you need to enable HTTP/3 on your own server.

Table of contents

Open Table of contents

A quick recap of the predecessors

HTTP/1.1 (1997) — one connection serves one request at a time. To load a page with dozens of files, the browser opens 6 parallel TCP connections per domain and still hits a queue. Hence hacks like sprites and bundled CSS.

HTTP/2 (2015) brought multiplexing: many logical streams over a single connection. Noticeably faster, but one fundamental problem remained — hidden one layer down, in TCP.

Protocol stack: HTTP/1.1, HTTP/2 and HTTP/3

The problem TCP can’t solve

TCP guarantees byte delivery in strict order. That’s exactly its weak spot. HTTP/2 sends several streams over one TCP connection, but TCP doesn’t see streams — it sees a single byte stream. Lose one packet and TCP halts delivery of all data that arrived after it until the lost packet is retransmitted. Even data belonging to other, fully received streams.

This is head-of-line blocking. Invisible on a fast wired network, but on a lossy mobile link HTTP/2 sometimes behaves no better than HTTP/1.1.

Head-of-line blocking in TCP vs independent QUIC streams

What QUIC changes

QUIC is a transport protocol on top of UDP, originally built at Google and standardized by the IETF in RFC 9000. UDP guarantees neither order nor delivery — QUIC implements all of that itself, but now with awareness of streams. The key differences:

Number of round-trips to the first byte of data

Side by side

HTTP/1.1HTTP/2HTTP/3
Year199720152022
TransportTCPTCPQUIC / UDP
Multiplexingnoyesyes
Head-of-lineyes (HTTP+TCP)yes (TCP)no
Encryptionoptionalde facto TLSmandatory (TLS 1.3)
Handshake1+ RTT1+ RTT1 / 0 RTT
Network changedropsdropsseamless

What you need to enable HTTP/3

Good news: in production it’s usually a couple of config lines. You need three things.

1. A server that speaks QUIC. Caddy does HTTP/3 out of the box. Nginx — from the 1.25 branch onward (the ngx_http_v3_module, built with BoringSSL/QUIC). HAProxy, Cloudflare and most CDNs handle it too.

2. TLS 1.3. QUIC won’t run without it. If you already have a valid certificate and TLS 1.3 enabled, this box is ticked.

3. An open UDP/443. The most common “it won’t start” cause: the firewall only allows TCP/443. QUIC travels over UDP and must be allowed explicitly.

A minimal Caddy example — HTTP/3 is on automatically, no extra directives needed:

example.com {
	reverse_proxy localhost:8080
}

For Nginx 1.25+, enable quic on listen and advertise support to the client via the Alt-Svc header:

server {
    # TCP for HTTP/1.1 and HTTP/2
    listen 443 ssl;
    # UDP for HTTP/3 (QUIC)
    listen 443 quic reuseport;

    ssl_protocols TLSv1.3;

    # tell the browser: "I speak HTTP/3, come over on it"
    add_header Alt-Svc 'h3=":443"; ma=86400';

    server_name example.com;
    # ...
}

Don’t forget the firewall:

# open UDP/443 for QUIC
sudo ufw allow 443/udp

How browsers actually use it

An important detail: the browser does not connect over HTTP/3 right away. The first request almost always goes over HTTP/2 on TCP. In the response the server sends an Alt-Svc: h3=":443" header, meaning “you can also reach me over HTTP/3.” The browser remembers that and establishes its next connections to that host over QUIC. So HTTP/3 “kicks in” on the second visit — that’s normal.

How to verify it works

The simplest check, working with any curl, is to see whether the server advertises HTTP/3 via the Alt-Svc header:

curl -sI https://example.com | grep -i alt-svc
# alt-svc: h3=":443"; ma=86400

If the header is there, the server correctly tells browsers it supports HTTP/3. This doesn’t need HTTP/3 in curl itself (the stock build from Ubuntu/Debian repos is almost always compiled without QUIC) — the header is served over plain HTTPS.

To see an actual HTTP/3 connection — in the browser DevTools Network tab, enable the Protocol column: requests will show h3.

If you don’t have an HTTP/3-capable curl on hand, the easiest check is online via http3check.net: enter your site’s address and the service reports whether HTTP/3 and QUIC are supported, which QUIC versions respond, the Alt-Svc header the server returns, and TLS certificate details. Handy for confirming HTTP/3 is actually reachable from the outside, not just in your own config.

Is it worth switching

For a typical site on a fast wired connection the difference will be small. HTTP/3’s real win shows where networks are unreliable: mobile traffic, regions far from the server, frequent Wi-Fi/LTE handoffs. Fewer RTTs on the handshake, no stream blocking under loss, seamless network migration — all of it directly improves load time on a weak link.

The risk is minimal: HTTP/3 layers on top of existing HTTP/2 and HTTP/1.1, not in place of them. A browser that can’t do QUIC (or a network where UDP/443 is closed) simply stays on HTTP/2. You can turn it on and just watch.

Bottom line: HTTP/3 isn’t cosmetics — it’s moving the transport from TCP to QUIC/UDP. The price is mandatory encryption and an open UDP port; the payoff is no head-of-line blocking, a 0–1 RTT handshake, and connections that survive a network change.


Share this post:

Previous Post
Deploy Astro to Cloudflare Pages: Git Integration and GitHub CI/CD
Next Post
Container Security: A Practical Checklist for Implementation