Configure NGINX HTTP/2 server push and connection multiplexing

Advanced 25 min Apr 30, 2026 109 views
Ubuntu 24.04 Debian 12 AlmaLinux 9 Rocky Linux 9

Configure NGINX HTTP/2 server push and connection multiplexing to reduce page load times by up to 50% through proactive resource delivery and efficient connection reuse for high-performance web applications.

Prerequisites

  • NGINX 1.18+ with HTTP/2 support
  • SSL/TLS certificates configured
  • Root or sudo access

What this solves

HTTP/2 server push and connection multiplexing eliminate the need for multiple TCP connections and reduce round-trip times by proactively sending resources to clients. This configuration optimizes NGINX to deliver CSS, JavaScript, and images before the browser requests them, while multiplexing multiple requests over a single connection.

Prerequisites

Before configuring HTTP/2 server push and multiplexing, ensure you have:

  • NGINX 1.18+ installed with HTTP/2 support
  • SSL certificates configured (HTTP/2 requires HTTPS)
  • Root or sudo access to the server
  • Basic understanding of NGINX configuration
Note: HTTP/2 server push requires SSL/TLS encryption. If you need help setting up SSL certificates, check out our NGINX SSL certificate automation tutorial.

Step-by-step configuration

Verify HTTP/2 support

First, confirm your NGINX installation supports HTTP/2 and check the current version.

nginx -V 2>&1 | grep -o with-http_v2_module

You should see with-http_v2_module in the output. If not, you'll need to recompile NGINX or install a version with HTTP/2 support.

Enable HTTP/2 in server blocks

Edit your main NGINX configuration to enable HTTP/2 on your SSL-enabled virtual hosts.

server {
    listen 443 ssl http2;
    listen [::]:443 ssl http2;
    server_name example.com www.example.com;
    
    ssl_certificate /etc/ssl/certs/example.com.crt;
    ssl_certificate_key /etc/ssl/private/example.com.key;
    
    # HTTP/2 push configuration
    location = /index.html {
        http2_push /css/main.css;
        http2_push /js/app.js;
        http2_push /images/logo.png;
    }
    
    root /var/www/html;
    index index.html index.htm;
}

Configure HTTP/2 connection multiplexing

Add HTTP/2 specific settings to optimize connection multiplexing and stream handling.

http {
    # HTTP/2 connection multiplexing settings
    http2_max_concurrent_streams 128;
    http2_max_requests 1000;
    http2_max_field_size 16k;
    http2_max_header_size 32k;
    
    # Enable HTTP/2 server push by default
    http2_push_preload on;
    
    # Optimize buffer sizes for HTTP/2
    client_body_buffer_size 128k;
    client_max_body_size 10m;
    client_header_buffer_size 1k;
    large_client_header_buffers 4 4k;
    
    # Enable gzip compression for HTTP/2
    gzip on;
    gzip_vary on;
    gzip_min_length 10240;
    gzip_proxied expired no-cache no-store private must-revalidate auth;
    gzip_types
        text/plain
        text/css
        text/xml
        text/javascript
        application/javascript
        application/xml+rss
        application/json;
}

Configure automatic server push with preload headers

Set up automatic server push based on Link preload headers sent by your application.

server {
    listen 443 ssl http2;
    server_name example.com;
    
    # Enable automatic push based on Link headers
    http2_push_preload on;
    
    location / {
        # Add preload headers for critical resources
        add_header Link "; rel=preload; as=style" always;
        add_header Link "; rel=preload; as=script" always;
        add_header Link "; rel=preload; as=font; crossorigin" always;
        
        try_files $uri $uri/ =404;
    }
    
    # Specific push rules for landing page
    location = / {
        http2_push /css/critical.css;
        http2_push /js/critical.js;
        http2_push /images/hero.webp;
    }
}

Optimize HTTP/2 performance settings

Configure advanced HTTP/2 performance parameters for high-traffic scenarios.

http {
    # HTTP/2 performance optimization
    http2_recv_buffer_size 256k;
    http2_chunk_size 8k;
    
    # Connection keep-alive for HTTP/2
    keepalive_timeout 300s;
    keepalive_requests 10000;
    
    # Worker process optimization
    worker_processes auto;
    worker_connections 4096;
    worker_rlimit_nofile 8192;
    
    # Enable efficient file serving
    sendfile on;
    tcp_nopush on;
    tcp_nodelay on;
    
    # Optimize SSL for HTTP/2
    ssl_session_cache shared:SSL:10m;
    ssl_session_timeout 10m;
    ssl_session_tickets off;
    
    # Modern SSL configuration
    ssl_protocols TLSv1.2 TLSv1.3;
    ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384;
    ssl_prefer_server_ciphers off;
}

Configure conditional server push

Set up smart server push that avoids pushing resources already cached by the client.

map $http_cookie $should_push_css {
    default 1;
    "~*css-cached" 0;
}

map $http_cookie $should_push_js {
    default 1;
    "~*js-cached" 0;
}

server {
    listen 443 ssl http2;
    server_name example.com;
    
    location / {
        # Conditional push based on cookie presence
        if ($should_push_css) {
            http2_push /css/main.css;
        }
        
        if ($should_push_js) {
            http2_push /js/app.js;
        }
        
        # Set cache control headers
        location ~* \.(css|js)$ {
            expires 1y;
            add_header Cache-Control "public, immutable";
            add_header Set-Cookie "css-cached=1; Path=/; Max-Age=31536000" always;
        }
    }
}

Test configuration and reload NGINX

Validate your NGINX configuration and apply the changes.

sudo nginx -t
sudo systemctl reload nginx

Verify HTTP/2 server push configuration

Test your HTTP/2 configuration and verify server push is working correctly.

# Check HTTP/2 support
curl -I -H "Accept-Encoding: gzip" --http2 https://example.com/

Test server push with verbose output

curl -v --http2 https://example.com/ 2>&1 | grep -E "(< HTTP/2|< :status|pushed)"

Check HTTP/2 connection multiplexing

for i in {1..5}; do curl -s -w "@curl-format.txt" --http2 https://example.com/ & done; wait

Create a curl format file to measure timing:

time_namelookup:  %{time_namelookup}s\n
time_connect:     %{time_connect}s\n
time_appconnect:  %{time_appconnect}s\n
time_pretransfer: %{time_pretransfer}s\n
time_total:       %{time_total}s\n

Monitor HTTP/2 performance

Set up monitoring to track HTTP/2 performance metrics and server push effectiveness.

http {
    # Enable detailed logging for HTTP/2
    log_format http2_combined '$remote_addr - $remote_user [$time_local] '
                              '"$request" $status $body_bytes_sent '
                              '"$http_referer" "$http_user_agent" '
                              'rt=$request_time uct="$upstream_connect_time" '
                              'uht="$upstream_header_time" urt="$upstream_response_time" '
                              'h2="$http2" push="$http2_pushed"';
    
    access_log /var/log/nginx/access.log http2_combined;
}

Monitor HTTP/2 connections and performance:

# Monitor HTTP/2 connections
sudo ss -tlnp | grep :443

Check NGINX HTTP/2 statistics

sudo tail -f /var/log/nginx/access.log | grep "h2=\"2\""

Monitor server push effectiveness

awk '$NF ~ /push="[1-9]"/ {pushed++} END {print "Pushed resources:", pushed+0}' /var/log/nginx/access.log

For comprehensive performance monitoring, consider integrating with our NGINX Prometheus monitoring setup.

Common issues

SymptomCauseFix
HTTP/2 not working Missing SSL configuration Enable SSL/TLS with listen 443 ssl http2
Server push not triggering Incorrect resource paths Use absolute paths like /css/main.css, not relative
High memory usage Too many concurrent streams Lower http2_max_concurrent_streams to 64
Connection errors Buffer size too small Increase http2_recv_buffer_size to 512k
Slow initial page load Pushing too many resources Limit to 2-3 critical resources per page
Browser compatibility issues Old SSL configuration Update to TLSv1.2+ and modern ciphers

Optimize server push strategies

Implement advanced server push strategies for different content types and user scenarios.

# Different push strategies by content type
location /blog/ {
    # Push critical blog assets
    http2_push /css/blog.css;
    http2_push /js/blog.js;
}

location /shop/ {
    # Push e-commerce specific resources
    http2_push /css/shop.css;
    http2_push /js/cart.js;
    http2_push /images/placeholder.svg;
}

Mobile-specific push strategy

map $http_user_agent $is_mobile { default 0; "~*Mobile" 1; } location / { if ($is_mobile) { http2_push /css/mobile.css; } if (!$is_mobile) { http2_push /css/desktop.css; } }

Performance testing and benchmarking

Use these tools to measure HTTP/2 server push and multiplexing performance improvements.

# Install HTTP/2 testing tools
sudo apt update
sudo apt install -y curl apache2-utils

Benchmark HTTP/2 vs HTTP/1.1

ab -n 1000 -c 10 -H "Accept-Encoding: gzip" https://example.com/

Test concurrent connections (HTTP/2 multiplexing)

seq 1 10 | xargs -I {} -P 10 curl -s -w "Total: %{time_total}s\n" --http2 https://example.com/

Measure server push effectiveness

curl -v --http2 https://example.com/ 2>&1 | grep -c "< HTTP/2 200 pushed"

Next steps

Running this in production?

Want this handled for you? Running this at scale adds a second layer of work: capacity planning, failover drills, cost control, and on-call. See how we run infrastructure like this for European teams.

Need help?

Don't want to manage this yourself?

We handle infrastructure performance optimization for businesses that depend on uptime. From initial setup to ongoing operations.