ThisCalculator

Everyday

Nginx Speed Optimization: A Practical Guide

Updated · Standard formula, shown below

Nginx Speed Optimization: A Practical Guide

This guide walks you through the most effective Nginx configuration changes to reduce latency, improve throughput, and lower server load. You’ll learn how to tune caching, compression, keepalive connections, and OS-level settings—each step is concrete and can be applied to a typical production server.

What You’ll Need

  • A server running Nginx (any modern version, 1.18+ recommended)
  • Root or sudo access to edit Nginx configuration files
  • Basic familiarity with the command line
  • Access to your Nginx config files (usually /etc/nginx/nginx.conf and files in /etc/nginx/conf.d/ or /etc/nginx/sites-available/)

Step-by-Step

  1. Back up your current configuration. Before changing anything, copy your existing config: sudo cp /etc/nginx/nginx.conf /etc/nginx/nginx.conf.bak. Also back up any site configs you’ll edit.
  2. Set the number of worker processes. In nginx.conf, set worker_processes auto; so Nginx uses one worker per CPU core. This maximizes parallel request handling.
  3. Tune worker connections. Set worker_connections to a higher value, like 4096 or 8192. This controls how many simultaneous connections each worker can handle. Monitor memory usage—each connection uses a small amount of RAM.
  4. Enable keepalive connections. In your http block, add:
    keepalive_timeout 65;
    keepalive_requests 100;

    This allows clients to reuse the same TCP connection for multiple requests, reducing handshake overhead. For upstream servers (like PHP-FPM), add a keepalive pool in your upstream block:

    upstream php_backend {
        server 127.0.0.1:9000;
        keepalive 32;
    }

    And in the location that proxies to it, set proxy_http_version 1.1; and proxy_set_header Connection "";.

  5. Enable gzip compression. In the http block, add:
    gzip on;
    gzip_comp_level 5;
    gzip_min_length 256;
    gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript image/svg+xml;

    This reduces the size of text-based responses. Avoid compressing already-compressed formats like JPEG or PNG.

  6. Set up caching for static files. In your server or location blocks, add:
    location ~* \.(jpg|jpeg|png|gif|ico|css|js|pdf)$ {
        expires 30d;
        add_header Cache-Control "public, no-transform";
    }

    This tells browsers to cache static assets for 30 days, reducing repeat requests.

  7. Enable open file cache. In the http block, add:
    open_file_cache max=1000 inactive=20s;
    open_file_cache_valid 30s;
    open_file_cache_min_uses 2;
    open_file_cache_errors on;

    This caches file descriptors and metadata, speeding up static file serving.

  8. Tune TCP settings. In the http block, add:
    tcp_nopush on;
    tcp_nodelay on;

    tcp_nopush optimizes sending response headers, while tcp_nodelay reduces latency for keepalive connections.

  9. Adjust client body buffer size. If your site handles file uploads, set client_max_body_size 10m; (or your desired limit) and client_body_buffer_size 16k; to avoid excessive memory usage.
  10. Disable access logs for static files (optional). For high-traffic static content, you can skip logging to reduce I/O:
    location ~* \.(jpg|jpeg|png|gif|ico|css|js)$ {
        access_log off;
        ...
    }

    Be aware this loses audit trail for those files.

  11. Use HTTP/2. In your server block, add listen 443 ssl http2; (if using SSL). HTTP/2 multiplexes requests over a single connection, significantly improving page load times.
  12. Set up microcaching for dynamic content (advanced). If using PHP-FPM, you can cache responses for a short time (e.g., 1-5 seconds) to reduce backend load:
    fastcgi_cache_path /var/cache/nginx levels=1:2 keys_zone=mycache:100m inactive=60m;
    fastcgi_cache_key "$scheme$request_method$host$request_uri";
    location ~ \.php$ {
        ...
        fastcgi_cache mycache;
        fastcgi_cache_valid 200 1s;
    }

    Test carefully—this can serve stale data if not configured properly.

  13. Test and reload. After all changes, run sudo nginx -t to check for syntax errors. If OK, reload with sudo systemctl reload nginx (or sudo nginx -s reload).

Common Mistakes

  • Setting worker_processes too high (e.g., 8 on a 2-core server) can cause overhead and memory waste. Use auto.
  • Enabling gzip for images wastes CPU and may increase file size. Stick to text-based types.
  • Forgetting to set proxy_http_version 1.1 when using keepalive to upstreams—it silently disables keepalive.
  • Overly long cache expiration for HTML files can cause users to see stale content. Cache only assets with hashed filenames or short expiry.
  • Not testing after changes—a typo can take your site down. Always run nginx -t first.

Tips

  • Use gzip_static on; to serve pre-compressed files if you have them (e.g., .gz versions). This saves CPU.
  • Monitor your server with tools like htop and nginx -T to see effective config.
  • Consider using a CDN for static assets—Nginx still handles dynamic requests faster.
  • For SSL, enable session resumption: ssl_session_cache shared:SSL:10m; and ssl_session_timeout 10m; to reduce handshake overhead.

Troubleshooting

  • If Nginx fails to start after changes: Run sudo nginx -t to see the exact error. Common issues are missing semicolons or incorrect file paths.
  • If performance doesn’t improve: Check if your bottleneck is actually the backend (PHP, database). Use top to see CPU usage. If Nginx is idle but backend is busy, focus on caching and upstream tuning.
  • If you see “worker_connections are not enough” errors: Increase worker_connections or reduce the number of keepalive connections.
  • If gzip isn’t working: Verify that the response has Content-Type matching your gzip_types. Use curl -H “Accept-Encoding: gzip” -I to check.
  • If caching doesn’t seem to work: Check that the cache directory exists and is writable by the Nginx user. Also ensure your cache key is unique enough.

Frequently Asked Questions

How much of a speed improvement can I expect?

It varies. For static files, enabling caching and keepalive can reduce latency by 30-50%. For dynamic content, microcaching can cut response times dramatically if your backend is slow.

Should I use gzip or brotli?

Brotli generally compresses better, but requires the Nginx brotli module. If you can’t install it, gzip is fine. You can enable both, with brotli preferred when the client supports it.

Is it safe to disable access logs?

For high-traffic static files, yes, but you lose the ability to audit those requests. Consider keeping logs for dynamic pages and security-critical endpoints.

What is the ideal worker_connections value?

It depends on your RAM and expected traffic. Start with 4096 and monitor. Each connection uses about 0.5-1 KB of memory, so 8192 connections per worker is safe on a 4GB server.

Does HTTP/2 require SSL?

Yes, in practice. HTTP/2 is implemented over TLS in modern browsers, so you need a valid SSL certificate. Use Let’s Encrypt if you don’t have one.

Can I use these settings on a shared hosting plan?

No. These changes require access to Nginx configuration files, which shared hosting typically doesn’t provide. You’ll need a VPS or dedicated server.

Related

Method: the standard formula for this calculation, rounded as each result states. See how the calculators work or report an error.