Skip to main content
Picture going to a coffee shop every morning and getting the same order. The first time the barista prepares your drink it takes a little time. After a few visits the barista remembers your order and has it ready before you ask. In this analogy: the barista is the server, the coffee is the data, and you are the user. Without caching, every request forces the server to regenerate or fetch data anew, wasting time and resources. A cache is like the barista remembering and preparing your order in advance — when you request it, it’s served faster and the backend works less. NGINX commonly acts as a caching reverse proxy: it accepts client requests, forwards them to the backend only when needed, and stores responses to speed up later requests.

Example NGINX proxy caching configuration

Below is a typical configuration that enables proxy caching. Read the following sections for detailed explanations of each directive.

Key directives explained

proxy_cache_path

  • Sets where cached files are stored and configures the shared memory zone for keys/metadata.
  • Example details:
    • /var/lib/nginx/cache — directory to store cached files (ensure NGINX can read/write).
    • levels=1:2 — creates a two-level subdirectory layout (e.g., /cache/a/b/...) to avoid many files in a single directory.
    • keys_zone=app_cache:8m — shared memory zone named app_cache with 8 MB for keys and metadata.
    • max_size=50m — optional on-disk cap (use G to specify gigabytes).

proxy_cache_key

  • Determines the unique key used to look up cached responses. Customize as needed for your application.
  • Common key:
  • Components:
    • $schemehttp or https.
    • $request_methodGET, POST, etc. (Normally cache GET; be cautious with POST.)
    • $host — host header (e.g., www.example.com).
    • $request_uri — path + query string.
A simple diagram illustrating NGINX proxy cache flow: a request goes to NGINX, which uses a proxy_cache_key to retrieve or store cached assets. On the right are cached static files (HTML, JS, CSS, GIF) labeled "Cache Data."
When a request maps to an existing cache entry it’s a HIT — NGINX serves the cached content. If there’s no match it’s a MISS — NGINX sends the request to the backend and, depending on caching rules, stores the response.

proxy_cache_valid

  • Controls how long responses are kept in cache depending on HTTP status code.
  • Example:
  • In this configuration: 200 and 302 responses are cached for 10 minutes; 404 responses for 1 minute.

Enabling caching in server/location blocks

  • Reference the same keys_zone declared in proxy_cache_path:

proxy_cache_bypass — use with caution

proxy_cache_bypass lets you skip cache for specific requests (for example, when the client sends Cache-Control: no-cache). Overusing this directive defeats caching because many requests will be forwarded to the backend. Prefer bypass rules only for dynamic endpoints or authenticated requests.
Example:

Expose cache status for debugging

  • The variable $upstream_cache_status indicates HIT, MISS, BYPASS, EXPIRED, etc.
  • To make this visible in a browser’s network inspector:
Use add_header to expose cache status in response headers to the client (useful for debugging). proxy_set_header is different — it sets headers on the request to the upstream backend.

How to confirm caching is working

  • Quick method: browser DevTools
    1. Open DevTools (Inspect).
    2. Go to the Network tab.
    3. Select a resource and inspect response headers for X-Proxy-Cache, X-Cache, or Cache-Status.
  • You can also inspect NGINX or backend logs for cache-related messages.
A diagram titled "Confirmation" showing a browser window and a flow from "Network Tab" to "Resource" to "X-Cache or Cache Status." It illustrates using the browser's developer tools to inspect a page and check cache status.
A sample response header block might include:
  • X-Cache or X-Proxy-Cache showing HIT indicates a cached response.
  • Age shows how long the response has been in cache.

Clearing the cache

  • Remove files under the cache directory (for example, delete contents inside /var/lib/nginx/cache) or rename the cache directory.
  • If you remove files while NGINX is running, in-memory metadata may still reference deleted entries — reload or restart NGINX after clearing to reset the cache state.
  • NGINX will recreate the cache files when it starts writing new entries.

Next steps

  • Start by caching static assets (images, CSS, JS) — these are safe and high-impact.
  • Add cache for specific dynamic endpoints after validating correctness.
  • Use X-Proxy-Cache (or a similar header) to verify cache behavior in your environment.
Now you can configure NGINX caching using the directives shown above and verify results with the browser DevTools and server logs.

Watch Video