In Nginx reverse proxy configurations, caching behavior depends on how cache keys are defined, evaluated, and stored on disk. By default, the ngx_http_proxy_module directive proxy_cache_key defines the identifier used for caching. Modifying this directive allows administrators to partition cached responses by custom variables, cookies, or subrequest byte ranges. This guide explains how Nginx evaluates proxy_cache_key, how MD5 hashing maps keys to disk directories via proxy_cache_path levels, how to configure range keys with ngx_http_slice_module, and what documented limitations apply.
Default Cache Key Construction and Evaluation
The ngx_http_proxy_module documentation defines the syntax for proxy_cache_key as:
proxy_cache_key string;
The documented default value is:
proxy_cache_key $scheme$proxy_host$request_uri;
The documentation also states that by default, the directive’s value is close to the string:
proxy_cache_key $scheme$proxy_host$uri$is_args$args;
This directive is supported in the http, server, and location contexts.
Method conversion also affects key handling. The directive proxy_cache_convert_head defaults to on (introduced in version 1.9.7), enabling conversion of the HEAD method to GET for caching. When proxy_cache_convert_head is set to off, the documentation states that the cache key should be configured to include $request_method.
How MD5 Hashing and Directory Levels Map Keys to Disk
Cache data are stored in files on disk. The documentation specifies that the file name in a cache is the result of applying the MD5 function to the cache key.
The levels parameter of proxy_cache_path sets hierarchy levels of a cache from 1 to 3, where each level accepts values 1 or 2:
proxy_cache_path /data/nginx/cache levels=1:2 keys_zone=one:10m;
Under levels=1:2, file names in the cache follow this hierarchy structure:
/data/nginx/cache/c/29/b7f54b2df7773722d382f4809d65029c
In addition, all active keys and information about data are stored in a shared memory zone configured by keys_zone. A 1-megabyte zone can store about 8 thousand keys (or about 4 thousand keys with commercial subscription extended cache information). Cached data not accessed during the period set by the inactive parameter (defaulting to 10 minutes) are removed regardless of freshness.
A cached response is first written to a temporary file, and then the file is renamed. Starting from version 0.8.9, temporary files and the cache can reside on different filesystems, but Nginx copies the file across two filesystems instead of performing a cheap rename. The documentation recommends placing both the cache and the directory holding temporary files on the same filesystem for any given location.
Customizing Cache Keys with Cookies and Variables
The documentation gives an example of defining a key with variables and client cookies:
proxy_cache_key "$host$request_uri $cookie_user";
This example incorporates the request $host, $request_uri, and the client cookie value $cookie_user into the cache key string.
Bypass conditions can also be defined using proxy_cache_bypass:
proxy_cache_bypass $cookie_nocache $arg_nocache$arg_comment;
proxy_cache_bypass $http_pragma $http_authorization;
If at least one value of the string parameters is not empty and is not equal to “0”, the response will not be taken from the cache.
Configuring Range Slices with ngx_http_slice_module
The ngx_http_slice_module (introduced in version 1.9.8) is a filter that splits a request into subrequests, each returning a certain range of response, providing more effective caching of big responses. The module is not built by default and must be enabled at compile time with --with-http_slice_module.
The documented example configuration pairs proxy_cache_key with the slice filter:
location / {
slice 1m;
proxy_cache cache;
proxy_cache_key $uri$is_args$args$slice_range;
proxy_set_header Range $slice_range;
proxy_cache_valid 200 206 1h;
proxy_pass http://localhost:8000;
}
Documented requirements for this configuration include:
- Slice Size: The
slicedirective sets the size of the slice (such as1m). The default value0disables splitting responses into slices. Note that a value that is too low may result in excessive memory usage and opening a large number of files. - Header Propagation: The
$slice_rangevariable holds the current slice range in HTTP byte range format (for example,bytes=0-1048575) and should be passed to the proxied server as theRangerequest header field viaproxy_set_header Range $slice_range;. - Cache Key Inclusion: If caching is enabled,
$slice_rangeshould be added to the cache key so each slice is cached independently. - Status Code Support: Caching of responses with the
206status code must be explicitly enabled (for example, withproxy_cache_valid 200 206 1h;).
Documented Limitations and Known Issues
The primary source excerpts document several operational limitations:
- Slice Subrequests and Background Updates: The
ngx_http_slice_moduledocumentation notes as a known issue that the module currently does not work as expected in subrequests such as background cache update (proxy_cache_background_update), because the request is constructed without byte-range support. - Cache Header Invalidation on Upgrade: In Nginx versions 1.7.3, 1.7.7, and 1.11.10, the internal cache header format changed; previously cached responses are considered invalid after upgrading to these versions.
- Commercial Purge Disk Retention: Under commercial subscription purging (
proxy_cache_purge), if the purge cache key ends with an asterisk (*), all matching entries are removed from the cache, but files remain on disk until deleted for inactivity, processed by the cache purger (introduced in 1.7.12), or accessed by a client.

Text version of the diagrams
- Cache Key vs Disk Path: Cache key — Variables form identifier; MD5 filename — Key becomes digest; Directory levels — Digest prefix structures path
- Whole Response vs Slices: Whole response — Key identifies full request; Slice range — Range becomes key input; 206 caching — Partial responses enabled
Research Methodology and Limitations
This article was prepared directly from visible excerpts of the public Nginx documentation for ngx_http_proxy_module and ngx_http_slice_module. Material limitations affect independent verification: the provided ngx_http_proxy_module excerpt is truncated, omitting surrounding context and unreferenced directive details. Furthermore, the retrieved secondary URL from DigitalOcean contained only generic navigation text without technical caching documentation, preventing any substantive comparative analysis. No runtime benchmarks, custom test scripts, or unverified external sources were used.


