Skip to main content

HTTP/3 and QUIC on Linux VPS: Cut Lag on Mobile Links

HTTP/3 and QUIC on UDP cut the stalls that TCP makes on 4G and 5G links. Here is how to set up HTTP/3 in Nginx and set the Linux UDP buffers.

Cover image for HTTP/3 and QUIC on Linux VPS: Cut Lag on Mobile Links

Over 80 percent of web visits in India come from phones. They use 4G or 5G links. When signals fade or packets drop in a busy city, HTTP/2 over TCP stalls. HTTP/3 and QUIC over UDP remove that stall. Pages load fast. Time to First Byte (TTFB) drops.

CDNs have had HTTP/3 at their edges for years. But running QUIC on your own origin gives bigger gains. You get more for live APIs. You get more for signed in pages. It also helps self hosted apps. Modern Nginx supports HTTP/3 out of the box. Setting it up on your own Linux host is easy and safe to run.

How HTTP/3 and QUIC fix TCP head-of-line blocking.

HTTP/2 lets a browser ask for many assets (HTML, CSS, images) over one TCP link. That solved the old HTTP/1.1 queue problem. But TCP sets strict byte order. If one packet drops, the whole stream pauses.

QUIC is the transport that HTTP/3 runs on. It runs over UDP, not TCP. Each asset downloads in its own stream. If one stream stalls, the others keep going.

When a packet drops on Stream A, the client tells the host right away. The host sends that packet again. Streams B, C, and D go on without a pause. On cell links with 2 to 4 percent packet loss, HTTP/3 delivers pages 25 to 40 percent faster than HTTP/2.

HTTP versions at a glance.

FeatureHTTP/1.1HTTP/2HTTP/3
TransportTCP.TCP.UDP via QUIC.
Parallel downloads6 TCP links per host.1 link, many streams.1 UDP session, each stream its own.
Head-of-line blockingYes, at the app layer.Yes, at the TCP layer.No.
First handshake2 to 3 round trips.2 round trips.1 round trip, plus 0-RTT for repeat visits.
Cell link impactModerate.High stalls on packet loss.Low. Only one stream recovers.
Keeps a live link when IP changesNo.No.Yes, via a 64-bit ID.

Connection migration: staying online when phones switch networks.

A TCP link binds to four values. Your IP, your port, the host IP, and the host port. When your phone leaves WiFi and joins 5G, your IP changes. The TCP link breaks. The browser must close all active requests. It must look up DNS again. Then it must run a new TCP and TLS handshake. Only then does it resume.

QUIC uses a 64-bit Connection ID, not the IP four-tuple. When your phone switches networks, the client sends its Connection ID from the new IP address. The host checks it and keeps the session alive. Active downloads, live API calls, and form posts go on without a pause. For e-commerce checkouts and SaaS apps, this ends the cart drops and broken sessions that TCP causes on mobile.

Does HTTP/3 speed up TTFB and Core Web Vitals?

Yes. The gains are biggest on mobile and for guests who come back.

Time to First Byte (TTFB).

TTFB is the gap between a click and the first byte of the page. On a fresh TCP plus TLS link, the client must finish three steps. First, a DNS lookup, if it is not cached. Second, a TCP three-way handshake (1 round trip). Third, a TLS 1.3 handshake (1 round trip).

That is at least 3 round trips. On a 60ms mobile link, those handshakes alone eat 180ms. Your host has not run a single line of code yet.

QUIC joins transport and crypto into one round trip. For guests who come back and cached the crypto details, 0-RTT mode sends the page request inside the very first packet. On slow mobile links, 0-RTT cuts TTFB by 100 to 250ms.

Largest Contentful Paint (LCP).

LCP shows when the biggest thing on screen (a hero image, a banner, a heading) has loaded. TTFB is the start line for LCP. A fast host reply means the browser pulls the hero image sooner. QUIC also puts the LCP image in its own top stream. A lost packet on some other asset will not block it.

AI search crawler fetch deadlines.

AI engines such as PerplexityBot fetch live URLs under strict time limits. When pages load fast, they return full HTML before those engines time out. They then cite a faster site, not yours. See our guide on AI search crawlers and server performance for the full picture.

Does Googlebot use HTTP/3?

Yes. Google said that Googlebot talks HTTP/3 over QUIC when hosts offer it via the Alt-Svc header. Switching to UDP lets Googlebot crawl more pages within its crawl budget. It skips the TCP handshake cost on every request.

Configuring HTTP/3 and QUIC in Nginx.

You need Nginx 1.25.0 or newer with the ngx_http_v3_module. That module ships in the mainline packages from Nginx.

Step 1: Check for HTTP/3 support.

nginx -V 2>&1 | grep -o -- '--with-http_v3_module'

If the command prints --with-http_v3_module, you are ready. If it returns blank, upgrade:

sudo apt update
sudo apt install -y curl gnupg2 ca-certificates lsb-release ubuntu-keyring
curl https://nginx.org/keys/nginx_signing.key | gpg --dearmor \
  | sudo tee /usr/share/keyrings/nginx-archive-keyring.gpg >/dev/null
echo "deb [signed-by=/usr/share/keyrings/nginx-archive-keyring.gpg] \
  http://nginx.org/packages/mainline/ubuntu $(lsb_release -cs) nginx" \
  | sudo tee /etc/apt/sources.list.d/nginx.list
sudo apt update
sudo apt install -y nginx

Step 2: Configure the Nginx server block.

QUIC runs on UDP port 443. Your existing HTTPS still runs on TCP port 443. Nginx listens on both at once.

The first time a browser visits, it uses TCP. The host replies with an Alt-Svc header. The header says HTTP/3 is on UDP port 443. The browser moves to QUIC on the next visit.

Open your site config (for example, /etc/nginx/conf.d/example.com.conf) and add:

server {
    # TCP listeners — HTTP/2 fallback for older clients
    listen 443 ssl;
    listen [::]:443 ssl;

    # UDP listeners — QUIC / HTTP/3
    listen 443 quic reuseport;
    listen [::]:443 quic reuseport;

    server_name example.com www.example.com;

    # TLS certificates (TLS 1.3 required for HTTP/3)
    ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;
    ssl_protocols TLSv1.2 TLSv1.3;
    ssl_prefer_server_ciphers off;

    # QUIC-specific settings
    ssl_early_data on;
    quic_retry on;
    quic_gso on;

    # Tell browsers HTTP/3 is available on UDP 443 for the next 24 hours
    add_header Alt-Svc 'h3=":443"; ma=86400' always;

    # Security headers
    add_header X-Content-Type-Options "nosniff" always;
    add_header X-Frame-Options "SAMEORIGIN" always;

    root /var/www/example.com/public;
    index index.html index.php;

    location / {
        try_files $uri $uri/ /index.php?$args;
        proxy_set_header Early-Data $ssl_early_data;
    }

    location ~ \.php$ {
        include fastcgi_params;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
        fastcgi_pass unix:/run/php/php8.3-fpm.sock;
    }
}

Key settings explained.

  • The quic flag starts the QUIC listener on UDP 443. The reuseport flag lets several CPU cores share the UDP socket.
  • The Alt-Svc header says HTTP/3 is ready. The ma=86400 part tells browsers to keep that note for 24 hours. The always part puts the header on error pages too.
  • quic_gso on; hands big UDP packets straight to the network card. It cuts CPU use under heavy traffic.
  • ssl_early_data on; turns on 0-RTT for guests who come back.

Tuning Linux UDP buffers for QUIC.

TCP has decades of kernel tuning behind it. UDP buffers, by default, are sized for DNS queries and syslog. When QUIC traffic spikes, the default buffers overflow. The kernel drops packets. QUIC sends them again. Latency climbs.

Add these kernel settings to /etc/sysctl.d/60-quic.conf. They let you handle thousands of concurrent QUIC sessions.

# Allow 16 MB socket buffers
net.core.rmem_max = 16777216
net.core.wmem_max = 16777216
net.core.rmem_default = 4194304
net.core.wmem_default = 4194304

# Queue more packets during traffic bursts
net.core.netdev_max_backlog = 10000

# Use BBR congestion control for better throughput on lossy links
net.core.default_qdisc = fq
net.ipv4.tcp_congestion_control = bbr

Apply without rebooting:

sudo sysctl --system

Verify the settings:

sysctl net.core.rmem_max net.core.wmem_max

Pair this with fast local storage for Indian hosting. It keeps disk writes fast when QUIC sends data again or checkpoints it.

Opening UDP port 443.

HTTP/3 stops working if UDP 443 is blocked. TCP 443 is open on most hosts. QUIC needs UDP 443 allowed too.

For UFW:

sudo ufw allow 443/udp comment 'HTTP/3 QUIC'
sudo ufw status verbose

For raw iptables:

sudo iptables -A INPUT -p udp --dport 443 -m comment --comment "HTTP/3 QUIC" -j ACCEPT

If you use a cloud provider firewall (security groups, network ACLs), add an inbound UDP 443 rule there too.

Testing your HTTP/3 setup.

Browsers only find QUIC after a TCP visit. A first load that shows h2 in DevTools is normal.

Test with curl.

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

Look for HTTP/3 200 in the output. Also check the Alt-Svc header over TCP:

curl -I https://example.com | grep -i alt-svc

Test with Chrome DevTools.

  1. Open DevTools and go to the Network tab.
  2. Right-click a column header and check Protocol.
  3. Visit your site. The first load shows h2.
  4. Refresh without clearing cache. The protocol should show h3 for the main document and static assets.

If you still see h2, check that the Alt-Svc header is there. Also check that UDP 443 is not blocked.

Server CPU and QUIC.

QUIC is fast for users but needs more CPU than HTTP/2. TCP has had decades of hardware offload in network chips. QUIC encryption runs in software. Pick hosts with modern CPUs that support AES-NI speed up. Dedicated physical cores help when you run hundreds of dynamic QUIC links. Explore our app hosting plans.

Make sure Linux kernel 4.18 or newer is running so quic_gso on; works. Ensure reuseport is active so traffic spreads across all Nginx worker processes.

Frequently asked questions.

Will enabling HTTP/3 break older browsers?

No. Clients that do not support QUIC ignore the Alt-Svc header. They stay on HTTP/2 or HTTP/1.1 over TCP. Your host answers both without any disruption.

Why does my browser use HTTP/2 on the first visit?

Browsers cannot probe UDP port 443 without causing delay on every new link. The first visit always uses TCP. The host replies with Alt-Svc: h3=":443". The browser keeps that note and moves to QUIC on the next visit.

Does 0-RTT resumption introduce security risks?

Only for state change requests such as POST. RFC standards limit 0-RTT to safe, repeatable requests (GET and HEAD). Nginx passes the ssl_early_data value to backends. You can block or set aside early data requests.

Does HTTP/3 need a new SSL certificate?

No. HTTP/3 uses the same TLS certificates you already use for HTTPS. The keys and cert chain are the same. Only the transport changes from TCP to QUIC.

Written by

Renish Mithani

Hosted in India, written in English

  • 12 min read

Share this post

Need help?

Ask us on WhatsApp

Our team replies during Indian business hours. Ask us anything about hosting, and we will help. We are the people who run the servers, so we can answer the hard ones too.

That is the end of this post. If you want to keep reading, the posts below are the ones we share with it. We write every post ourselves, and each one stands on its own.

We write about hosting, servers, backups, and the day to day work of running a site for a customer. There is no sales pitch in a post, and every post is free to read.

We write them for the people who run a site from India, and we keep the words plain. We do not write for a prize, and we do not sell you anything here. Read the post, take what you need, and ignore the rest.

Related posts

We rank these by the tags they share with the post you came from. Read one to learn more. Every post is free to read.

Cookie Preferences