Site icon GetPageSpeed

Practical guide: tuning http2_chunk_size in NGINX

http2_chunk_size

http2_chunk_size

What http2_chunk_size controls

We’ve run a testing of various settings that vary payload size and http2_chunk_size so you don’t have to.

Quick tuning picks for various payload sizes (based on our measured results)

Combined policy (latency + throughput)

Rule-of-thumb formula for http2_chunk_size

If you’d like a simple sizing rule from payload size S (bytes) to one of {4k, 8k, 16k}:

Why: aim to keep the number of chunks per response roughly within 4–64 for typical assets, minimizing overhead without starving other streams.

Per-location examples

The http2_chunk_size is supported in location context, which means you may tune it up as needed.
So armed with knowledge on which locations store which payload sizes on average, the ultimate tuning is setting up the right chunk size in the right location:

server {
    listen 443 ssl;
    http2 on;
    # Baseline
    http2_chunk_size 8k;

    # Small/interactive
    location ~ \.php$ {
        http2_chunk_size 4k;
        fastcgi_pass …;
    }
    location /css/         { http2_chunk_size 4k; }
    location /js/          { http2_chunk_size 8k; }

    # Large/static
    location /downloads/   { http2_chunk_size 16k; }
}

If NGINX terminates TLS in front of Varnish

When NGINX terminates TLS, you usually have a single root location in your TLS side of things:

location / {
    listen 443 ssl;
    http2 on;
    proxy_set_header … ;
    proxy_pass …;
}

You can’t allocate a location \.php$ to set up an optimized chunk size there. However, armed this time with a knowledge that your typical framework does SEO-friendly URLs, you can set up an extra location that targets URIs without extensions. For example /some/article would end up there.

In other words, add a dedicated “extensionless” location for SEO‑friendly URLs (usually dynamic pages going to PHP via Varnish). These responses are typically small; prefer a low chunk size for latency:

upstream varnish { server 127.0.0.1:6081; }

server {
    listen 443 ssl;
    http2 on;

    # Shared proxy headers (inherited by locations)
    proxy_set_header Host $host;
    proxy_set_header X-Forwarded-Proto $scheme;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;

    # Baseline
    location / {
        http2_chunk_size 8k;
        proxy_pass http://varnish;
    }

    # Extensionless URLs (no dot anywhere in path) → dynamic pages (favor latency)
    location ~ ^/[^.]+$ {
        http2_chunk_size 4k;
        proxy_pass http://varnish;
    }

    # Static assets → larger chunk for throughput
    location ~* \.(?:css|js|png|jpe?g|gif|svg|ico|woff2?)$ {
        http2_chunk_size 16k;
        proxy_pass http://varnish;
    }
}

Notes and caveats

Exit mobile version