Skip to content

HTTP/3 on Windows Server: IIS can, Nginx Win32 cannot

Verified 2 min read

Enable HTTP/3 on IIS/ASP.NET Core with HTTPS and EnableHttp3, advertise it with Alt-Svc, test QUIC over UDP 443, and understand the Windows Nginx limit.

Tested onStandard / Datacenter · Build 26100.33650 · x64
E1
Build
26100.33650
Edition
Standard / Datacenter
Architecture
x64
Support
Documentation (E1)
Evidence
E1Official documentation
Verified
2026-10-29
Page type
Concept

HTTP/3 is HTTP over QUIC/UDP, not TCP. On Windows:

  • IIS / ASP.NET Core supports HTTP/3 on Windows Server 2022 / Windows 11+ with an HTTPS binding and EnableHttp3.
  • Nginx on Windows cannot build ngx_http_v3_module; do not claim Windows Nginx HTTP/3.
  • If you need HTTP/3 at the edge, use IIS, a Linux Nginx/Caddy tier, or a CDN — and test it.

HTTP/3 is not automatically faster for every app. It helps on lossy/high-latency links and removes TCP head-of-line blocking; it does not fix a slow database.

  • Windows Server 2022 or later / Windows 11+.
  • An HTTPS binding (https, certificate, SNI).
  • EnableHttp3 registry value.
  • UDP 443 allowed through the firewall and any NAT.
  • A client that supports HTTP/3 (current Chrome/Edge/Firefox) and can reach UDP 443.

Enable:

Terminal window
New-ItemProperty -Path 'HKLM:\SYSTEM\CurrentControlSet\Services\HTTP\Parameters' `
-Name EnableHttp3 -PropertyType DWord -Value 1 -Force

Reboot (or restart the HTTP stack during a maintenance window). Do not bounce HTTP.sys on a busy server without a plan; it affects every HTTP listener, not just IIS.

Browsers discover HTTP/3 from HTTP/1.1 or HTTP/2 via Alt-Svc:

Alt-Svc: h3=":443"; ma=86400

IIS does not always add it for you. For ASP.NET Core, add it early in the pipeline:

app.Use((context, next) =>
{
context.Response.Headers.AltSvc = "h3=\":443\"";
return next(context);
});

IIS can also send an Alt-Svc HTTP/2 frame with EnableAltSvc; that path requires hostname-based netsh certificate bindings, not IP-only bindings.

The first request normally uses HTTP/1.1 or HTTP/2, then the client upgrades. That is expected; it is not “HTTP/3 failed”.

  • In-process ASP.NET Core: the request reports HTTP/3.
  • Out-of-process (IIS → Kestrel): IIS speaks HTTP/3 to the client, but the reverse-proxy hop to Kestrel is HTTP/1.1, so HttpRequest.Protocol reports HTTP/1.1.

Do not use HttpRequest.Protocol alone to prove the client used HTTP/3 in an out-of-process deployment.

Terminal window
netsh http show sslcert hostnameport=lab.example:443
Get-NetFirewallRule -DisplayName '*HTTP*' | Select-Object DisplayName,Enabled
curl.exe --http3 -I https://lab.example/

curl --http3 only works if the curl build includes HTTP/3 support. In a browser, DevTools → Network → Protocol column should show h3 after the Alt-Svc upgrade. If it shows h2, the client did not switch; check UDP 443 and Alt-Svc.

The official ngx_http_v3_module documentation states the module cannot be built on the Win32 platform. There is no supported Windows Nginx HTTP/3 termination to enable with a config flag.

Options:

  • terminate HTTP/3 at IIS or a Linux reverse proxy/CDN;
  • keep Windows Nginx on HTTP/2 and accept that;
  • do not advertise h3 from a server that cannot serve it.
  • Mobile/lossy networks, large numbers of parallel assets.
  • You already have TLS/HTTP/2 and can open UDP 443.
  • You can measure (RUM or controlled clients), not just run a lab curl.

Not worth it when:

  • the app is API-only with tiny requests and a fast network;
  • your edge cannot pass UDP;
  • you would have to break HTTP/2 fallback to “prove” HTTP/3.

E1. The lab did not enable IIS HTTP/3 or test QUIC; it only documented the requirements. Nginx 1.28.0 on Windows 11 was verified for HTTP/1.1 on 8081, not HTTP/3. The Nginx Win32 limitation is from the official module documentation.

Sources