← Blog

Nginx with HTTP/3 and QUIC in 2026: when to turn it on and when not to bother

HTTP/3 over QUIC is production-ready in Nginx 1.26.x. Here's how to switch it on step by step, what you actually gain and the cases where sticking with HTTP/2 still makes sense.

The protocol that lived under "experimental" for years

Two years ago, when a client asked if we could turn HTTP/3 on for their Nginx, the honest answer was "we can, but we wouldn't recommend it in production". The ngx_http_v3_module landed in Nginx 1.25.0 in June 2023 marked experimental, which meant what it usually means: works in demos, breaks in specific places you'd rather not discover on a Tuesday afternoon.

In 2026 the conversation has shifted. With Nginx 1.26.x and OpenSSL 3.5.x or BoringSSL/quiche, HTTP/3 over QUIC is production-ready in the meaning sysadmins give the word: you flip it on, watch it for a couple of weeks and stop thinking about it.

Let's look at when it's worth the move, how to do it, and what still bites.

What HTTP/3 actually buys you (one page)

QUIC replaces TCP underneath and rewrites the contract with the network:

  • 1-RTT handshake (or 0-RTT on resume). Versus TCP + TLS, which needs three round-trips before the first byte goes out.
  • No head-of-line blocking between streams: if a packet carrying the logo image gets lost, the article HTML doesn't sit waiting.
  • Transparent connection migration: phone switches Wi-Fi → 4G and the TLS session survives. Same promise HTTP/2 over TCP made… except it never actually worked.
  • Encrypted by default: QUIC doesn't allow plain text. Sounds obvious in 2026, but it forces certificate hygiene that many servers don't have.

What HTTP/3 doesn't buy you:

  • It's not a magic fix for sites slow at the backend. If the bottleneck is PHP-FPM or the database, HTTP/3 doesn't touch it.
  • It doesn't replace HTTP/2. The right approach is to serve both: HTTP/2 over TCP/443 and HTTP/3 over UDP/443, and let the client negotiate.

When to turn it on (and when to stick with HTTP/2)

Turning it on is worth it when:

  • You have meaningful mobile traffic. That's the scenario where QUIC shows up in real metrics.
  • You serve an international site with users on unreliable networks.
  • Your Core Web Vitals are sitting right at the edge and you need to claw back tenths in LCP/INP.

Turning it on isn't worth it if:

  • The box is a small VPS with little CPU headroom. QUIC moves work from the kernel (TCP) into user space (QUIC). The compute bill is real: at high load, Nginx does more work serving HTTP/3 than HTTP/2 for the same request count.
  • You sit behind a corporate firewall that filters UDP/443. Yes, it happens more than people think — especially in enterprise networks with out-of-date SD-WAN.
  • You already have a CDN doing HTTP/3 down to the client. In that case the HTTP/2 origin-to-CDN leg doesn't need upgrading.

Step-by-step rollout

1. Check versions

nginx -V 2>&1 | grep -oE 'OpenSSL [0-9.]+'   # OpenSSL 3.5.1 or later
nginx -V 2>&1 | grep ngx_http_v3              # should show up

If ngx_http_v3_module doesn't appear, your package wasn't compiled with HTTP/3. Debian 13 ships it in the official package; on Ubuntu 24.04 LTS you need the official Nginx PPA (nginx.org/packages/ubuntu) or a recompile. Caveat: the apt version on Ubuntu 22.04 still doesn't include the module on many derived repos.

2. Configure the server block

Minimum working block for a domain that already serves TLS:

server {
    # HTTP/2 over TCP (keep)
    listen 443 ssl;
    listen [::]:443 ssl;
    http2 on;

    # HTTP/3 over QUIC
    listen 443 quic reuseport;
    listen [::]:443 quic reuseport;
    http3 on;
    http3_hq off;

    # Advertise HTTP/3 availability to the client
    add_header Alt-Svc 'h3=":443"; ma=86400' always;

    server_name www.example.com example.com;

    ssl_certificate     /etc/letsencrypt/live/example.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;
    ssl_protocols       TLSv1.3;       # QUIC requires TLS 1.3
    ssl_early_data on;                  # optional, enables 0-RTT

    root /var/www/example;
    index index.html;
}

Critical bits:

  • reuseport only on the first listen ... quic. Without it, Nginx workers can't efficiently share the same UDP port.
  • Alt-Svc is how the browser learns you speak HTTP/3. The first request is still HTTP/2; from the second one, the browser tries QUIC. Skip the header and you'll never see HTTP/3.
  • TLS 1.3 is mandatory. Your config can keep TLSv1.2 for HTTP/2 — QUIC ignores that branch.

3. Open the firewall

This one gets forgotten more than you'd expect:

sudo ufw allow 443/udp     # Ubuntu/Debian
sudo firewall-cmd --permanent --add-port=443/udp && sudo firewall-cmd --reload  # RHEL family

If you sit behind a load balancer (HAProxy, AWS NLB, etc.), the LB has to forward UDP/443. Many cloud LBs only balance TCP by default. Without UDP/443 open end-to-end, HTTP/3 never reaches the server.

4. Reload and verify

sudo nginx -t
sudo systemctl reload nginx

External test:

curl --http3 -I https://example.com

If you see HTTP/3 200, you're done. If you see HTTP/2 200, the server answers but the client didn't ask for HTTP/3 (use --http3-only to force and diagnose).

Browser test: Chrome or Firefox → DevTools → Network → the "Protocol" column should show h3 on the second reload (the first one is always h2 because of the Alt-Svc negotiation).

What we've seen in production

Some real numbers from the last six months, with no sugar:

  • Mid-sized e-commerce site, ~80% mobile traffic: LCP -8% measured on Chrome UX Report after enabling HTTP/3. Nice. Not life-changing.
  • Corporate site, mostly desktop on fibre: no visible difference. The Alt-Svc negotiation adds a couple of bytes to the first response and that's about it.
  • International site with users in Latin America and Africa: 200-400ms TTFB improvement on high-latency networks. Here it shows.
  • Small VPS (1 vCPU, 2 GB RAM) serving a static blog with occasional spikes: CPU went up by about 6% average, no visible upside. We turned it off again.

Takeaway: measure before and after, don't assume.

What still bites

  • reuseport requires a recent kernel (4.5+). Anything you've kept updated has it, but check if you're stuck on an old distro.
  • Some intermediate CDNs still don't speak HTTP/3 between origin and edge. If Cloudflare sits in front, the client already sees HTTP/3 (Cloudflare delivers it) and the origin upgrade adds nothing.
  • Diagnosis is more opaque: capturing QUIC traffic isn't like capturing TCP. You need a recent Wireshark, SSLKEYLOGFILE and patience. If you're used to debugging HTTP/2 with tcpdump, brace yourself.
  • Legacy tools (old curl, wget, certain monitoring agents) don't speak HTTP/3. Make sure Alt-Svc doesn't break your monitoring pipeline.

Should we turn it on for your server?

Our advice in one sentence: if you have meaningful mobile traffic and recent kernel + Nginx, yes. Otherwise, wait for the next server refresh and do it then. It's not a change that fixes a problem; it's a change that adds headroom where there wasn't any.

If you want us to size it up for your case, drop us a line. The activation itself takes about an hour; the audit beforehand so you don't break monitoring or firewalls, another. The rest is measuring.

References

Want to talk about your case?

Tell us what you need and we will get back to you within 24 hours with a clear proposal.

Get a quote