How To

Fix Nginx proxy_headers_hash Warning

Nginx throws the [warn] could not build optimal proxy_headers_hash warning when its internal hash table runs out of space to store proxy headers. This typically happens on servers running multiple reverse proxy configurations with many proxy_set_header and proxy_hide_header directives across different server blocks.

Original content from computingforgeeks.com - post 26425

The warning itself does not break Nginx – it still starts and serves traffic. But it means Nginx fell back to a non-optimal hash configuration, which affects performance on every proxied request. This guide walks through the fix for proxy_headers_hash, plus related hash warnings for server_names_hash and map_hash that often appear on the same server. Full documentation for these directives is available in the Nginx proxy module reference.

Step 1: Understand the Nginx Hash Warning

The full warning looks like this:

nginx: [warn] could not build optimal proxy_headers_hash, you should increase either proxy_headers_hash_max_size: 512 or proxy_headers_hash_bucket_size: 64; ignoring proxy_headers_hash_bucket_size

Nginx uses hash tables internally to look up header names quickly during request proxying. Two settings control the hash table behavior:

  • proxy_headers_hash_max_size – the total size of the hash table (default: 512). Think of this as the number of slots available
  • proxy_headers_hash_bucket_size – the size of each individual bucket (default: 64). This must be large enough to hold the longest header name

When you have many proxy headers defined across your server blocks, the default values are too small. Nginx cannot fit all header names into the hash table at the default size, so it logs the warning and falls back to a linear search – slower but functional.

Step 2: Fix proxy_headers_hash Settings

The fix goes in the http block of your main Nginx configuration file. These are global directives – they cannot be placed inside individual server or location blocks. Open the Nginx config file:

sudo vi /etc/nginx/nginx.conf

Add these two directives inside the http { } block, before any include statements or server blocks:

http {
    # Fix proxy_headers_hash warning
    proxy_headers_hash_max_size 1024;
    proxy_headers_hash_bucket_size 128;

    # ... rest of your config
}

For servers proxying a large number of backends (10+ sites), you may need even larger values:

    proxy_headers_hash_max_size 2048;
    proxy_headers_hash_bucket_size 256;

Start with 1024/128 and double them if the warning persists after reloading Nginx.

On servers with many virtual hosts, you may also see this related warning:

nginx: [warn] could not build optimal server_names_hash, you should increase either server_names_hash_max_size: 512 or server_names_hash_bucket_size: 64

This is the same type of hash table issue, but for server_name directives instead of proxy headers. If you have long domain names or many virtual hosts, the default bucket size is not large enough. The fix is similar – add these directives in the http block of /etc/nginx/nginx.conf:

http {
    server_names_hash_max_size 1024;
    server_names_hash_bucket_size 128;

    # ... rest of config
}

Servers hosting 50+ domains with long subdomain names may need server_names_hash_bucket_size 256. If you manage many virtual hosts on Nginx, increasing this proactively saves you from hitting the warning later.

If your Nginx configuration uses map blocks for URL rewrites, variable mapping, or geo-blocking, you might encounter this warning:

nginx: [warn] could not build optimal map_hash, you should increase either map_hash_max_size: 2048 or map_hash_bucket_size: 64

Large map blocks with hundreds of entries (common for redirect maps or user-agent filtering) need bigger hash tables. Add these in the http block:

http {
    map_hash_max_size 4096;
    map_hash_bucket_size 128;

    # ... rest of config
}

Redirect maps with 500+ entries may require map_hash_max_size 8192 or higher. Scale the value based on the number of entries in your largest map block.

Step 5: Test and Reload Nginx

After making changes, always test the configuration before reloading. A syntax error in nginx.conf will prevent Nginx from restarting entirely. Run the config test:

sudo nginx -t

A successful test returns no warnings about hash sizes and confirms the syntax is valid:

nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful

If the hash warning still appears, double the max_size value and test again. Once the test passes cleanly, reload Nginx to apply changes without dropping active connections:

sudo systemctl reload nginx

Verify Nginx is running with the new configuration:

sudo systemctl status nginx

The output should show active (running) with no recent error messages in the journal. If you previously saw hash warnings every time Nginx started, they should now be gone.

Step 6: Understand Hash Sizing in Nginx

Nginx requires bucket_size values to be powers of 2 (64, 128, 256, 512). This is because Nginx aligns hash buckets to CPU cache line boundaries for performance. Most modern CPUs use 64-byte cache lines, which is why 64 is the default bucket size.

The relationship between the three hash parameters works like this:

  • max_size controls how many total buckets the hash table contains. More buckets means fewer collisions and faster lookups
  • bucket_size controls how much data each bucket can hold. This must be at least as large as the longest key (header name, server name, or map key) plus internal overhead
  • Increasing max_size uses more memory but keeps lookups fast. Increasing bucket_size wastes cache lines but handles longer keys

The general approach is: increase max_size first (cheaper in terms of performance), and only increase bucket_size if your keys are genuinely long. For more detail on how Nginx handles hash tables internally, see the Nginx hash documentation.

Step 7: Prevent Hash Warnings with Proper Config Structure

Hash warnings tend to appear on servers where proxy configurations have grown organically over time. A few structural practices prevent the issue from recurring.

First, consolidate common proxy headers into a shared snippet file instead of repeating them in every server block:

sudo vi /etc/nginx/snippets/proxy-headers.conf

Add your standard proxy header directives:

proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Forwarded-Host $host;
proxy_set_header X-Forwarded-Port $server_port;

Then include the snippet in each server block instead of duplicating the headers:

server {
    listen 80;
    server_name app.example.com;

    location / {
        proxy_pass http://127.0.0.1:3000;
        include snippets/proxy-headers.conf;
    }
}

Second, remove any proxy_set_header directives that duplicate what Nginx already sends by default. The Host, Connection, and basic forwarding headers are common duplicates in configs copied from Stack Overflow.

Third, set the hash size directives in your main nginx.conf proactively, even before you hit the warning. This is especially relevant if you run a reverse proxy setup for Jenkins or similar tools where many custom headers are required. A reasonable starting point for a multi-site reverse proxy server:

http {
    # Proactive hash sizing for multi-site reverse proxy
    proxy_headers_hash_max_size 1024;
    proxy_headers_hash_bucket_size 128;
    server_names_hash_max_size 1024;
    server_names_hash_bucket_size 128;

    include /etc/nginx/conf.d/*.conf;
    include /etc/nginx/sites-enabled/*;
}

This approach handles growth gracefully. Adding new proxied backends will not trigger hash warnings until the server count exceeds what 1024/128 can accommodate – which is well over 50 sites for most header configurations.

Conclusion

The Nginx proxy_headers_hash warning is a sizing issue, not a configuration error. Increasing proxy_headers_hash_max_size and proxy_headers_hash_bucket_size in the http block of nginx.conf resolves it immediately. Apply the same approach to server_names_hash and map_hash warnings when they appear.

For production reverse proxy servers, set these values proactively during initial setup. Combined with shared proxy header snippets, this keeps the configuration clean as the number of proxied backends grows. If you are also seeing 413 Request Entity Too Large errors or need to enable Gzip and Brotli compression, those are common next steps when tuning an Nginx proxy.

Related Articles

Ubuntu How To Install ISPConfig Control Panel on Ubuntu 22.04 Web Hosting How To Install Multiple PHP versions on cPanel Web Hosting Configure IIS Web Server on Windows Server 2019 Debian Install PHP 8.5 on Debian 13/12 with Nginx and PHP-FPM

Leave a Comment

Press ESC to close