Tuning compression, files and keepalive

NGINX · Expert · 14 min

Default settings are conservative; a few targeted changes give large gains, while cargo-cult tuning wastes time.

Start by measuring ($request_time, $upstream_response_time, a load-testing tool). Then the settings that usually matter:

Compression: gzip on; with gzip_types for text formats (HTML is always included) and gzip_min_length 1024. Level 4 to 6 is the sweet spot; higher costs CPU for little gain. Don't gzip images or video, which are already compressed. gzip_static on; serves precompressed .gz files from the build, costing no CPU. Brotli needs a third-party module.

Static files: sendfile on; sends file data inside the kernel; tcp_nopush on; sends headers and the file start together; tcp_nodelay on; (default) avoids delays for small keepalive writes. open_file_cache max=10000 inactive=30s; caches file descriptors and metadata for sites with many small files.

Connections: client keepalive_timeout (default 75s) and keepalive_requests (default 1000) control reuse; upstream keepalive avoids TCP and TLS setup to backends, often the biggest win for proxies. TLS session caching and HTTP/2 reduce handshakes.

Buffers: proxy_buffers and proxy_buffer_size sized for typical responses avoid writing to temp files; the error log warns "an upstream response is buffered to a temporary file" when they're too small. client_body_buffer_size does the same for uploads.

Example

http {
    sendfile    on;
    tcp_nopush  on;
    keepalive_timeout 30s;
    open_file_cache          max=10000 inactive=30s;
    open_file_cache_valid    60s;

    gzip            on;
    gzip_comp_level 5;
    gzip_min_length 1024;
    gzip_types      text/css application/javascript application/json image/svg+xml;
    gzip_vary       on;                 # Vary: Accept-Encoding for caches

    proxy_buffer_size 16k;              # response headers
    proxy_buffers     16 16k;           # body buffers per connection

    server {
        listen 80;
        location /assets/ { root /var/www; gzip_static on; expires 1y; }
    }
}

Remember

  • gzip text at level 4-6; gzip_static serves prebuilt .gz files
  • sendfile, tcp_nopush and open_file_cache speed static serving
  • Upstream keepalive and buffer sizing matter most for proxies

Watch out for

  • Gzipping already-compressed images, burning CPU for no size gain.

Check yourself

  1. The error log keeps saying an upstream response is buffered to a temporary file. What should you consider?

Sign in to answer, see the explanations, and get this lesson back as a quick review later.

Official docs: nginx.org/en/docs/http/ngx_http_gzip_module.html

Builds on

Unlocks

Nothing builds on this yet.