Zit Seng's Blog

A Singaporean's technology and lifestyle blog

Experimenting with QUIC and HTTP/3

Today, as you access my website, there are two under-the-hood changes. The first is a move from Apache to Nginx software, and the other, is the new support for QUIC and HTTP/3. These are interrelated, and the new QUIC with HTTP/3 is a continual evolutionary improvement in the engineering of this website.

A bit of history: The Apache web server software came into existence in 1995. It’s based on the NCSA httpd, the place where the original and first-ever graphical-based web browser Mosaic was born. Apache was very popular, pretty much the de facto open source web server software in the ~2000 era. Few alternative software gained much traction. Nginx, first released in 2004, was a notable success.

This month, for the first time, the Netcraft Web Server Survey put Nginx ahead of Apache, commanding a 21.37% vs 21.18% share of top million busiest websites. (Nginx overtook Apache in share of all websites in April 20219.)

I’ve been using Apache to run this website since it started in 2007. I’m not unfamiliar with Nginx. I’ve used both software extensively in various work and personal projects. I use Nginx most often as a reverse proxy rather than to serve original content.

I don’t have complicated requirements for this website, so in principle, Nginx would have worked just fine. The best way to run a WordPress website like mine is to have php-fpm running the app, and while either Apache or Nginx would serve well as the front-end server, Nginx would likely have a performance advantage with lower resource requirements.

Back in 2007, I did evaluate both Apache vs Nginx, and in own benchmarks, Apache won out. I did do a reevaluation some years later, and Apache still emerged my pick.

However, since last year, I’ve been thinking about some new things to do on my website. In 2018, I started supporting HTTP/2 on this website by using an alternative build of Apache for Ubuntu. (It is not that I don’t know how to build software on my own, but I want to avoid having to tediously keep up with building updates myself.)

The successor to HTTP/2 is, of course, HTTP/3. There is a fundamental change in HTTP/3. Instead of running on top of TCP like the older versions of HTTP, HTTP/3 runs on top of QUIC, which uses UDP instead of TCP. QUIC, pronounced “quick”, is a new transport layer network protocol that, in simple terms, makes HTTP/3 run faster by avoiding extraneous RTT (round-trip time) from TCP handshakes.

Apache, unfortunately, hasn’t gotten very far with their own Apache QUIC development. Nginx also doesn’t yet have QUIC support in production, but at least their QUIC development work has progressed enough to offer binary preview builds. Check out Nginx’s QUIC page.

Wanting QUIC and moving to Nginx, thus, became a bundle deal that I had to take. There were some downsides though. There’s no mod_pagespeed for Nginx’s experimental build, so I’ll have to forgo the pagespeed optimisation on this website.

As is always the case, I have to run benchmarks to know if there is any difference/improvement from the change. I did some page load tests, using the times reported by the browser developer tools, and I observe generally some improvement in speed. For example, the average page load time for the main homepage of this website is 309.8 ms when running Apache, while with Nginx+QUIC, this time improved to 244.4 ms.

The numbers over a couple of other page load types (e.g. of a post page, the admin dashboard, etc) show an improvement of about 20% going from Apache to Nginx+QUIC. My sample size is quite small, so this may not be statistically convincing. However, I think it is safe to say that Nginx+QUIC did not make things worse, and more likely, did make a small improvement. (I cannot automate this test easily enough CLI tools like wget or curl because they do not support QUIC.)

Moving ahead with Nginx+QUIC means I’ll lose not just mod_pagespeed, but also brotli compression support. The latter is probably a lesser problem.

There is still one quirkiness of my Nginx+QUIC setup. For some reason, HTTP/3 verification tools like HTTP/3 Check will say my website supports HTTP/3 and QUIC only when testing in IPv4 mode. When switching to Advanced test with IPv6 address used, the check fails with an error that “HTTP over TCP request to server failed”. I dumped traffic, and found that the standard test did use IPv6 already and that worked just fine; whereas in Advanced mode, not a single packet was received. How odd?

I’ve verified, that using a hostname that only receives an IPv4 address will pass the check by the above tool in both Standard and Advanced mode. For some reason, there is a problem with IPv6.

If you’re interested in setting up QUIC for your website, then you should check out the Nginx QUIC+HTTP/3 binary packages. It’s the easiest way to get QUIC up and running quickly. (Yeah, pun intended.)

[Note: Cover pic is just a photo of some servers. Nothing to do with Nginx+QUIC. Though, my website could certainly be running on one of those kinds of boxes.]

3 thoughts on “Experimenting with QUIC and HTTP/3

  1. Hey nice post

    I’m currently also trying to do some test with QUIC. Unfortunately I never used nginx before. I used the prebuilt binanries with the following nginx.conf:

    user nginx;
    worker_processes auto;

    error_log /var/log/nginx/error.log notice;
    pid /var/run/nginx.pid;

    events {
    worker_connections 1024;

    http {
    include /etc/nginx/mime.types;
    default_type application/octet-stream;

    log_format main ‘$remote_addr – $remote_user [$time_local] “$request” ‘
    ‘$status $body_bytes_sent “$http_referer” ‘
    ‘”$http_user_agent” “$http_x_forwarded_for”‘;

    access_log /var/log/nginx/access.log main;

    sendfile on;
    keepalive_timeout 65;

    server {

    listen 443 http3 reuseport; # QUIC
    listen 443 ssl; # TCP

    ssl_certificate certs/domain.crt;
    ssl_certificate_key certs/domain.key;
    ssl_protocols TLSv1.3;

    location / {
    add_header Alt-Svc ‘h3=”:$server_port”; ma=86400’;

    root /var/www/en.wikipedia.org/wiki/;
    index Wikipedia.html;

    include /etc/nginx/conf.d/*.conf;

    Unfortunately when I connect to the the site trough Google the network tab in the F12 menu always shows that I’m only using h2. Do you know by any chance if something with my config is wrong or would you mind sharing yours?

    1. There are a few more things I have like:

      quic_gso on;
      quic_retry on;
      ssl_early_data on;
      http3_max_concurrent_pushes 30;
      http3_push 10;
      http3_push_preload on;

      But none of them are required for h3 to work. HTTP/3 requires UDP. Confirm that your host/firewall allows UDP 443 through? You can also check if your nginx process has a UDP socket listening on port 443. (netstat -nape|grep nginx)

Leave a Reply

Your email address will not be published. Required fields are marked *

View Comment Policy