Detailed guide

Http2 Http3 Migration Guide

View contents

Complete Guide to HTTP/2 and HTTP/3 Migration for Web Performance

Introduction

Migrating to HTTP/2 and HTTP/3 is one of the highest-impact performance improvements you can make. Modern protocols offer significant speed improvements with relatively straightforward implementation. This guide provides comprehensive migration strategies for different server environments.

New to HTTP/2 and HTTP/3? Start with our beginner-friendly guide: 📖 Read: HTTP/2 & HTTP/3 Explained

Strategy 1: Nginx HTTP/2 and HTTP/3 Configuration

HTTP/2 Setup

# /etc/nginx/sites-available/default

server {
    listen 443 ssl http2;
    listen [::]:443 ssl http2;

    server_name example.com www.example.com;

    # SSL Certificate (required for HTTP/2)
    ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;

    # Modern TLS configuration
    ssl_protocols TLSv1.2 TLSv1.3;
    ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256;
    ssl_prefer_server_ciphers off;

    # HTTP/2 specific settings
    http2_push_preload on;          # Enable Link preload push
    http2_max_concurrent_streams 128;
    http2_idle_timeout 3m;

    root /var/www/html;
    index index.html;

    location / {
        try_files $uri $uri/ =404;
    }
}

# Redirect HTTP to HTTPS
server {
    listen 80;
    listen [::]:80;
    server_name example.com www.example.com;
    return 301 https://$server_name$request_uri;
}

HTTP/3 Setup (Nginx 1.25+)

# /etc/nginx/nginx.conf

http {
    # Enable HTTP/3 support
    http3 on;
    http3_hq on;

    server {
        # HTTP/3 over QUIC
        listen 443 quic reuseport;
        listen 443 ssl http2;

        server_name example.com;

        ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
        ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;

        # TLS 1.3 required for HTTP/3
        ssl_protocols TLSv1.3;
        ssl_early_data on;          # Enable 0-RTT

        # Advertise HTTP/3 support
        add_header Alt-Svc 'h3=":443"; ma=86400';

        # QUIC-specific settings
        quic_retry on;
        quic_gso on;

        location / {
            try_files $uri $uri/ =404;
        }
    }
}

Strategy 2: Apache HTTP/2 Configuration

Enable HTTP/2 Module

# /etc/apache2/mods-available/http2.load
LoadModule http2_module /usr/lib/apache2/modules/mod_http2.so

# Enable the module
# a2enmod http2

Virtual Host Configuration

# /etc/apache2/sites-available/example.conf

<VirtualHost *:443>
    ServerName example.com
    ServerAlias www.example.com

    # Enable HTTP/2
    Protocols h2 h2c http/1.1

    # SSL Configuration (required)
    SSLEngine on
    SSLCertificateFile /etc/letsencrypt/live/example.com/fullchain.pem
    SSLCertificateKeyFile /etc/letsencrypt/live/example.com/privkey.pem

    # Modern TLS settings
    SSLProtocol all -SSLv3 -TLSv1 -TLSv1.1
    SSLCipherSuite ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256
    SSLHonorCipherOrder off

    # HTTP/2 settings
    H2Direct on
    H2ModernTLSOnly off
    H2MaxSessionStreams 100
    H2WindowSize 65535

    DocumentRoot /var/www/html

    <Directory /var/www/html>
        Options -Indexes +FollowSymLinks
        AllowOverride All
        Require all granted
    </Directory>
</VirtualHost>

# HTTP to HTTPS redirect
<VirtualHost *:80>
    ServerName example.com
    Redirect permanent / https://example.com/
</VirtualHost>

Strategy 3: CDN-Based HTTP/2 and HTTP/3

Cloudflare Configuration

Cloudflare Dashboard → Speed → Optimization → Protocol Optimization

✅ HTTP/2: Enabled by default (automatic)
✅ HTTP/3: Enable in dashboard

Settings:
- HTTP/2 to Origin: Enable (if origin supports)
- HTTP/3: Toggle ON
- 0-RTT Connection Resumption: Enable

AWS CloudFront

{
  "DistributionConfig": {
    "HttpVersion": "http2and3",
    "Origins": {
      "Items": [{
        "OriginProtocolPolicy": "https-only",
        "CustomOriginConfig": {
          "OriginProtocolPolicy": "https-only",
          "HTTPSPort": 443,
          "OriginSSLProtocols": {
            "Items": ["TLSv1.2"],
            "Quantity": 1
          }
        }
      }]
    },
    "DefaultCacheBehavior": {
      "ViewerProtocolPolicy": "redirect-to-https",
      "AllowedMethods": ["GET", "HEAD", "OPTIONS"]
    }
  }
}

Vercel and Netlify

Both platforms automatically provide HTTP/2 and HTTP/3:

Vercel:
- HTTP/2: Automatic ✅
- HTTP/3: Automatic ✅
- No configuration needed

Netlify:
- HTTP/2: Automatic ✅
- HTTP/3: Automatic ✅
- No configuration needed

Strategy 4: Node.js HTTP/2 Server

Native HTTP/2 Implementation

// server.js
const http2 = require('http2');
const fs = require('fs');
const path = require('path');

const server = http2.createSecureServer({
  key: fs.readFileSync('server.key'),
  cert: fs.readFileSync('server.crt'),
  allowHTTP1: true  // Fallback for HTTP/1.1 clients
});

// Handle streams
server.on('stream', (stream, headers) => {
  const reqPath = headers[':path'];

  // Server push example (use sparingly)
  if (reqPath === '/' && stream.pushAllowed) {
    stream.pushStream({ ':path': '/styles.css' }, (err, pushStream) => {
      if (!err) {
        pushStream.respondWithFile(
          path.join(__dirname, 'public', 'styles.css'),
          { 'content-type': 'text/css' }
        );
      }
    });
  }

  // Respond to request
  const filePath = reqPath === '/' ? '/index.html' : reqPath;
  stream.respondWithFile(
    path.join(__dirname, 'public', filePath),
    { 'content-type': getContentType(filePath) },
    { onError: (err) => handleError(stream, err) }
  );
});

server.listen(443, () => {
  console.log('HTTP/2 server running on port 443');
});

Express with HTTP/2

// Using spdy package for HTTP/2 with Express
const spdy = require('spdy');
const express = require('express');
const fs = require('fs');

const app = express();

// Middleware and routes
app.use(express.static('public'));

app.get('/', (req, res) => {
  // Server push via Link header
  res.setHeader('Link', '</styles.css>; rel=preload; as=style');
  res.sendFile(__dirname + '/public/index.html');
});

const options = {
  key: fs.readFileSync('server.key'),
  cert: fs.readFileSync('server.crt'),
  spdy: {
    protocols: ['h2', 'http/1.1'],
    plain: false
  }
};

spdy.createServer(options, app).listen(443, () => {
  console.log('HTTP/2 server with Express running');
});

Strategy 5: Optimization Best Practices

Remove HTTP/1.1 Workarounds

After HTTP/2 Migration - What to Change:
┌─────────────────────────────────────────────────────────────┐
│ REMOVE These HTTP/1.1 Workarounds:                          │
│                                                             │
│ ❌ Domain sharding (multiple CDN domains)                   │
│    └── HTTP/2 multiplexes on single connection              │
│                                                             │
│ ❌ Excessive file concatenation                             │
│    └── Many small files now efficient                       │
│                                                             │
│ ❌ Image sprites (for all images)                           │
│    └── Individual images can load in parallel               │
│                                                             │
│ ❌ Inlining everything (CSS, JS, images)                    │
│    └── External files can be cached and pushed              │
│                                                             │
│ KEEP These Practices:                                       │
│                                                             │
│ ✅ Minification (still reduces bytes)                       │
│ ✅ Compression (gzip/Brotli still essential)                │
│ ✅ Caching (cache headers still critical)                   │
│ ✅ Code splitting (reasonable chunks, not one huge file)    │
│ ✅ Critical CSS (first-render optimization)                 │
└─────────────────────────────────────────────────────────────┘

Preload and Early Hints

<!-- Use preload with HTTP/2 push -->
<link rel="preload" href="/fonts/main.woff2" as="font" type="font/woff2" crossorigin>
<link rel="preload" href="/styles/critical.css" as="style">
<link rel="preload" href="/scripts/main.js" as="script">

<!-- Server-side Early Hints (103) -->
<!-- Nginx config -->
<!-- add_header Link "</styles.css>; rel=preload; as=style" early_hints; -->

Optimal Resource Chunking

// vite.config.js - Optimal chunking for HTTP/2
export default defineConfig({
  build: {
    rollupOptions: {
      output: {
        // Smaller chunks work better with HTTP/2
        manualChunks: {
          vendor: ['vue', 'vue-router', 'pinia'],
          utils: ['lodash', 'axios'],
        },
        // Target ~50-100KB per chunk
        chunkSizeWarningLimit: 100,
      },
    },
  },
});

Strategy 6: Testing and Verification

Testing HTTP/2 Support

# Using curl
curl -I --http2 -s https://example.com | head -1
# Expected: HTTP/2 200

# Check negotiated protocol
curl -v --http2 https://example.com 2>&1 | grep "ALPN"
# Expected: ALPN, server accepted to use h2

# nghttp tool (detailed HTTP/2 analysis)
nghttp -nv https://example.com

Testing HTTP/3 Support

# Using curl with HTTP/3 (requires curl 7.66+)
curl --http3 -I https://example.com

# Check Alt-Svc header
curl -I https://example.com 2>&1 | grep -i "alt-svc"
# Expected: alt-svc: h3=":443"; ma=86400

Online Testing Tools

Tool Purpose URL
HTTP/2 Test Verify HTTP/2 support https://tools.keycdn.com/http2-test
HTTP/3 Check Verify HTTP/3 support https://http3check.net
WebPageTest Full protocol analysis https://webpagetest.org
Lighthouse Performance audit Built into Chrome DevTools

Measuring Migration Impact

Before/After Comparison

BEFORE HTTP/2 Migration (HTTP/1.1):
├── Connections per page: 6-8 parallel
├── Time to First Byte: 450ms
├── Page Load Time: 3.2s
├── Total Requests: 45
└── Lighthouse Performance: 68

AFTER HTTP/2 Migration:
├── Connections per page: 1-2 multiplexed
├── Time to First Byte: 380ms (↓15%)
├── Page Load Time: 2.4s (↓25%)
├── Total Requests: 45 (same, but faster)
└── Lighthouse Performance: 82 (↑14 points)

AFTER HTTP/3 Migration:
├── Connections per page: 1 QUIC
├── Time to First Byte: 320ms (↓29%)
├── Page Load Time: 1.9s (↓40%)
├── 0-RTT for returning visitors
└── Lighthouse Performance: 89 (↑21 points)

Migration Checklist

Before going live, verify:

  • [ ] HTTPS is fully configured (required for HTTP/2)
  • [ ] TLS 1.2+ enabled, TLS 1.3 for HTTP/3
  • [ ] HTTP/2 enabled and working (test with curl)
  • [ ] Alt-Svc header advertising HTTP/3 (if enabled)
  • [ ] Domain sharding removed (use single domain)
  • [ ] Excessive bundling reduced
  • [ ] Server push configured sparingly (or disabled)
  • [ ] Fallback to HTTP/1.1 works for old clients
  • [ ] Performance metrics improved in testing
  • [ ] CDN supports HTTP/2 and HTTP/3

Continue optimizing your server configuration:

📚 Back to Performance SEO Hub - Explore all performance topics


References

  1. MDN Web Docs - HTTP/2
  2. MDN Web Docs - HTTP/3
  3. web.dev - Introduction to HTTP/2
  4. Cloudflare - HTTP/3 Support

Try It Yourself

Ready to check your site’s HTTP protocol support?

🔧 Download UXR SEO Analyzer (Free, 100% local analysis)


Disclaimer: The analyzers in this extension are reference guides based on official documentation from MDN, web.dev, and Chrome Developers. They do not represent absolute truths about how search engines evaluate your content—only search engines know their internal algorithms. Use these recommendations as a starting point to improve your site.

Last updated: December 15, 2025

Related articles

Related version

Introduction

Http2 Http3 Explained

HTTP/2 and HTTP/3 are modern versions of the HTTP protocol that dramatically improve how web pages load

Category hub

Hub

Performance Seo Hub

Performance is a critical ranking factor and directly impacts user experience

In the same category

Detailed guide

Ttfb Optimization Guide

Time to First Byte (TTFB) is the foundation of web performance—every millisecond of TTFB delays your entire page load

Detailed guide

Caching Headers Optimization Guide

HTTP caching is one of the most powerful performance optimizations available

Detailed guide

Text Compression Implementation Guide

Text compression can reduce transfer sizes by 60-90%, making it one of the highest-impact performance optimizations available