About this site
What this is
This site is a self-hosted HTTP/3 showcase. Each of the six demos picks one mechanism that separates HTTP/3 from HTTP/2 — multiplexing under loss, handshake latency, header compression, per-stream independence, 0-RTT resumption, and connection migration — and measures it in your own browser against a live HTTP/2 baseline. No assertions. No benchmarks recorded elsewhere and replayed to you. The numbers you see are the numbers your browser produced, this session, on this server.
The demos are deliberately interactive: you set the loss percentage, click Run, and watch the two protocols race. The side-rail shows the QUIC connection your browser is using right now, including a live tail of the protocol events behind the numbers.
Why no CDN
A content delivery network terminates QUIC at its edge — the connection your browser negotiates is to a CDN PoP, not to this machine. That means any measurement you make reflects the CDN's connection, not the protocol. The whole point of this project is to make HTTP/3 visible and verifiable, so putting a CDN in front would make the demos circular: you would be measuring someone else's infrastructure.
This site is served directly from one residential Windows machine. That comes with trade-offs: the upstream bandwidth of a home connection is a shared bottleneck, the host can sleep, and the public IP is dynamic. Those constraints are real and documented — they do not affect the protocol comparisons because both legs of every demo share the same connection and the same bottlenecks.
How it works
The stack has three layers:
- Caddy owns TLS, QUIC, and HTTP/3. It terminates all connections, issues and auto-renews the Let's Encrypt wildcard certificates via the Cloudflare DNS-01 challenge, and serves the static site files directly from the repository working tree. QUIC runs on UDP/443 alongside the TCP/443 listener; both share the same port.
- Go demo-backend answers all
/api/*requests. It is a plainnet/httpservice on127.0.0.1:8443; Caddy reverse-proxies to it. The backend handles per-demo logic: the tile server for the multiplexing and streams demos, the handshake-race ping endpoints, QPACK header re-encoding, 0-RTT session tracking, the migration stream, and the qlog event bus that feeds the sidebar. - WinDivert loss-helper is an elevated Windows service that applies real packet loss for the loss-dependent demos. It hooks into the network stack via WinDivert 2.2.2, filtering on outbound port 443 traffic, and drops packets at the configured rate for the duration of a run. A dead-man timer reverts the loss automatically; closing the handle (including on crash) is fail-safe. Only the multiplexing and per-stream demos use it.
The HTTP/2 baseline is an honest one. Caddy automatically advertises HTTP/3 via the Alt-Svc header on every site on the shared listener — including a site you intend to keep on HTTP/2. The h2-only.* comparison vhost explicitly strips Alt-Svc so no browser upgrades to QUIC on that host. Without the advertisement, a browser stays on HTTP/2 regardless of what the server supports, which is the correct baseline for the comparison.
Honesty rules
Every claim on this site is measured, not asserted. A few specific commitments:
- Labeled degradations. The 0-RTT demo distinguishes "0-RTT capable" (Caddy has the session ticket) from "confirmed ✓" (the server received and honored an Early-Data request). The migration demo reports "connection replaced" when the connection ID changed — not "migrated" — because a true QUIC migration without reconnection requires a two-network switch that the in-browser test cannot guarantee.
- DNS excluded where it would bias a comparison. The 0-RTT timing bars subtract
domainLookupEnd − domainLookupStartfrom the totals: the resumed leg has no DNS lookup (the name is cached), so including DNS would give it a structural head start unrelated to 0-RTT. - Re-encodings, not wire sniffs. The QPACK demo re-encodes the headers your browser actually sent through both the HPACK and QPACK encoders server-side and returns sizes only — never values. It cannot read the bytes your browser put on the wire; the numbers are what the wire would have cost.
- No results without a valid run. A run that ends degraded — h3 unavailable, lock contention, network error — records nothing to the proof scorecard.
Your scorecard
Visit /proof to see your personal scorecard: six claims, each verified (or waiting) by your own browser on this server. Every number there came from a run you started. Nothing is server-asserted.
Source is available on request — the repository has no public remote.