HTTP/3 and QUIC Implementation Guide [2026 Cheat Sheet]
Bottom Line
HTTP/3 is HTTP semantics over QUIC, not just “HTTP over UDP.” In practice, successful deployments depend on four things: TLS 1.3, UDP reachability, Alt-Svc discovery, and implementation-specific config for your edge stack.
Key Takeaways
- ›HTTP/3 is standardized in RFC 9114; QUIC transport is RFC 9000; QUIC uses TLS 1.3 per RFC 9001.
- ›Browsers often discover HTTP/3 through Alt-Svc, then silently fall back to HTTP/2 if UDP or certs fail.
- ›NGINX HTTP/3 support lives in ngxhttpv3_module; Caddy supports h3 by default; HAProxy enables client-side h3 in 2.7+.
- ›curl supports strict QUIC tests with --http3-only and upgrade testing with --http3 or --alt-svc.
- ›0-RTT can reduce repeat-connection latency, but only enable it for replay-safe request patterns.
HTTP/3 is no longer a research topic or a browser checkbox. By May 05, 2026, the implementation question is operational: which edge supports RFC 9114 cleanly, how do clients discover it, which flags are safe in production, and how do you prove traffic is actually riding QUIC instead of silently falling back to HTTP/2? This reference is optimized for that job: quick verification, deploy-ready config, and the operational gotchas that matter.
- HTTP/3 maps HTTP semantics onto QUIC; it does not reuse TCP.
- TLS 1.3 is foundational to QUIC security and handshake behavior.
- Alt-Svc is still the most common browser upgrade path into h3.
- curl, NGINX, Caddy, and HAProxy each expose different knobs for testing and rollout.
Protocol Map
Bottom Line
A correct HTTP/3 rollout is mostly a transport and discovery exercise: enable QUIC on UDP, serve valid TLS 1.3, advertise Alt-Svc where needed, and verify with a QUIC-capable client instead of assuming the browser really upgraded.
Standards you actually need
- RFC 9000: QUIC transport over UDP.
- RFC 9001: QUIC secured using TLS 1.3; clients must not negotiate older TLS versions.
- RFC 9114: HTTP/3 mapping of HTTP semantics onto QUIC.
- RFC 9204: QPACK header compression for HTTP/3.
- RFC 7838: Alt-Svc advertisement and caching semantics.
What changed versus HTTP/2
- Transport moved from TCP to UDP via QUIC.
- Request multiplexing no longer shares a single TCP loss domain.
- Header compression moved from HPACK to QPACK.
- Connection setup can benefit from 0-RTT on repeat connections.
- Connection migration becomes possible when the implementation supports it.
Official docs worth keeping open
- RFC 9000
- RFC 9001
- RFC 9114
- NGINX ngxhttpv3_module
- curl HTTP/3 docs
- Caddy server options
- HAProxy HTTP protocol support
Command Cheat Sheet
Live search filter
Use the filter below to scan commands by purpose. Keyboard shortcuts are listed right after it.
Shortcuts: / focus search, Esc clear, j/k move between command groups.
| Shortcut | Action | Use it for |
|---|---|---|
/ | Focus filter | Jump straight to command search |
Esc | Clear filter | Reset the command list quickly |
j | Next group | Scan downward without the mouse |
k | Previous group | Scan upward without the mouse |
Verify strict HTTP/3
- Use --http3-only when you want failure instead of fallback.
- Use this first when you are validating a new listener or edge rollout.
curl --http3-only https://example.comTest upgrade and fallback behavior
- --http3 attempts HTTP/3 with fallback to older HTTP versions.
- --alt-svc lets curl persist and reuse advertised alternative services.
curl --http3 -I -v https://example.com
curl --alt-svc altsvc.cache https://example.comTroubleshoot with a QUIC-capable curl container
- Useful when your local curl was built without HTTP/3 support.
- This example is documented by HAProxy for quick QUIC validation.
docker run -ti --rm alpine/curl-http3 \
curl --verbose --http3 --silent --head https://example.comBuild curl with HTTP/3 support
- curl documents ngtcp2 as the non-experimental backend path.
- Its docs note that OpenSSL 3.5.0+ requires ngtcp2 1.12.0+.
git clone --depth 1 --branch $NGHTTP3_VERSION https://github.com/ngtcp2/nghttp3
cd nghttp3
autoreconf -fi
./configure --prefix=/path/to/nghttp3 --enable-lib-only
make
make install
cd ..
git clone --depth 1 --branch $NGTCP2_VERSION https://github.com/ngtcp2/ngtcp2
cd ngtcp2
autoreconf -fi
./configure PKG_CONFIG_PATH=/path/to/openssl/lib/pkgconfig:/path/to/nghttp3/lib/pkgconfig \
LDFLAGS='-Wl,-rpath,/path/to/openssl/lib' \
--prefix=/path/to/ngtcp2 --enable-lib-only --with-openssl
make
make install
cd ..
git clone --depth 1 https://github.com/curl/curl
cd curl
autoreconf -fi
./configure PKG_CONFIG_PATH=/path/to/openssl/lib/pkgconfig \
LDFLAGS='-Wl,-rpath,/path/to/openssl/lib' \
--with-openssl=/path/to/openssl --with-ngtcp2=/path/to/ngtcp2 --with-nghttp3=/path/to/nghttp3
make
make installHow to read the results
- If --http3-only fails, treat that as a transport or TLS issue first, not an application issue.
- If --http3 succeeds but strict mode fails, your fallback path is masking a QUIC problem.
- If --alt-svc upgrades on the second request, discovery is working even if the initial request was not h3.
Server Configurations
NGINX: explicit QUIC listener plus Alt-Svc
NGINX documents ngxhttpv3_module as experimental. The module appeared in 1.25.0, is not built by default, and requires --with-httpv3module.
http {
log_format quic '$remote_addr - $remote_user [$time_local] '
'"$request" $status $body_bytes_sent '
'"$http_referer" "$http_user_agent" "$http3"';
access_log logs/access.log quic;
server {
listen 8443 quic reuseport;
listen 8443 ssl;
ssl_certificate certs/example.com.crt;
ssl_certificate_key certs/example.com.key;
location / {
add_header Alt-Svc 'h3=":8443"; ma=86400';
}
}
}- 0-RTT with OpenSSL requires care: NGINX documents that before 1.29.1, OpenSSL builds could not enable it regardless of
ssl_early_data. - Useful server-side knobs include http3, http3maxconcurrent_streams, http3streambuffer_size, quic_retry, quichostkey, quic_gso, and quic_bpf.
Caddy: h3 is already in the default protocol set
Caddy documents the default supported protocols as h1 h2 h3. It also exposes a 0rtt off server option when you need to disable early data explicitly.
{
servers {
protocols h1 h2 h3
0rtt off
}
}
example.com {
respond "HTTP/3 ready"
}- Use Caddy when you want the shortest path to a clean HTTPS plus h3 baseline.
- Use explicit server options when you need to standardize protocol policy across sites.
HAProxy: separate QUIC bind plus Alt-Svc
HAProxy documents client-side HTTP/3 support for 2.7+. For 2.8+, the alpn h3 argument is no longer required on the QUIC bind because it defaults to h3.
frontend example
bind :80
bind :443 ssl crt ssl.pem
bind quic4@:443 ssl crt ssl.pem alpn h3
http-request redirect scheme https unless { ssl_fc }
http-response set-header alt-svc "h3=\":443\";ma=900;"
default_backend webservers- For backend-side HTTP/3 over QUIC, HAProxy documents it as experimental in 3.3+.
- That backend path requires
expose-experimental-directivesinglobal.
backend servers
mode http
server s1 quic4@192.168.0.10:443 check maxconn 30 ssl verify required ca-file /etc/haproxy/ssl/myca.pemDeployment checklist
- Open and monitor UDP/443, not just TCP/443.
- Serve valid certificates and a modern TLS stack.
- Advertise Alt-Svc where your client population depends on it.
- Keep an explicit fallback path to HTTP/2 during rollout.
Advanced Usage
0-RTT: faster, but only for replay-safe patterns
- RFC 9001 allows application data on repeat connections using 0-RTT.
- Do not treat 0-RTT as universally safe for non-idempotent requests.
- Disable it where request replay would create billing, mutation, or auth side effects.
Retry, address validation, and migration
- NGINX quic_retry enables QUIC address validation.
- quichostkey lets tokens survive reloads instead of changing every restart.
- quic_bpf is documented for Linux 5.7+ and helps support connection migration.
server {
listen 443 quic reuseport;
listen 443 ssl;
quic_retry on;
quic_host_key /etc/nginx/quic.key;
}Performance tuning knobs that are real
- http3maxconcurrent_streams controls per-connection request concurrency in NGINX.
- http3streambuffer_size controls QUIC stream buffer sizing in NGINX.
- quic_gso enables batch send optimization where UDP_SEGMENT exists.
- Caddy exposes protocol and 0rtt policy centrally through server options.
Config hygiene for teams
- Keep Alt-Svc max-age short during rollout, then raise it after validation.
- Normalize large config snippets before review with the Code Formatter.
- Log negotiated protocol explicitly so you can separate h2 success from true h3 success.
Troubleshooting
Common failure modes
- UDP path blocked: QUIC never establishes, but TCP fallback makes the app look healthy.
- Bad Alt-Svc: clients never discover the h3 endpoint or cache the wrong authority/port.
- Self-signed or mismatched certs: browsers often refuse QUIC silently and fall back.
- Tooling mismatch: local curl may lack HTTP/3 even when the server is correct.
Fast triage order
- Run
curl --http3-onlyagainst the production hostname. - Check that UDP/443 is reachable through the full edge path.
- Inspect the Alt-Svc header and its advertised port.
- Confirm the server is logging negotiated protocol, not just total HTTPS traffic.
- Test with a containerized QUIC-capable client if your workstation build is suspect.
curl --http3-only -I -v https://example.com
curl --http3 -I -v https://example.com
curl --alt-svc altsvc.cache https://example.comMinimal mental model
- If strict h3 fails, fix transport or TLS first.
- If upgrade-only h3 works after Alt-Svc, discovery is the missing piece.
- If browsers disagree with curl, inspect cache, certificate policy, and UDP middleboxes next.
Frequently Asked Questions
How do I verify a server is actually using HTTP/3 and not falling back to HTTP/2? +
curl --http3-only https://example.com first. That forces a QUIC-only path, so a successful result is much stronger evidence than a browser page load, which may have quietly downgraded to HTTP/2.Do I need Alt-Svc to enable HTTP/3? +
Alt-Svc advertisement.Is 0-RTT safe to enable with QUIC? +
Why does my browser still use HTTP/2 after I configured HTTP/3? +
Get Engineering Deep-Dives in Your Inbox
Weekly breakdowns of architecture, security, and developer tooling — no fluff.