Nginx by examples: Caching

Nginx offers out of the box very efficient caching support where

As usual the setup is fairly trivial:

server {

    proxy_cache_path /tmp/nginx-cache levels=1:2 
      keys_zone=api_cache:10m max_size=10g inactive=60m;

    location /api {

        proxy_cache api_cache;

        # we allow only 1 req per URI to hit origin 
        # in case of a cache miss
        proxy_cache_lock on;

        # we add the X-Proxy-Cache header to our response to the client
        add_header X-Proxy-Cache $upstream_cache_status; 



In this example

By default Nginx will respect the cache headers are returned by the downstream server and the preferred way to manage the caching of replies is to set a Cache-Control header in the reply

Force cache #

In some cases we can’t modify our downstream servers to serve appropriate Cache-Control headers

In these circumstances we can force some generic caching policies as follows

location /api {

    proxy_cache api_cache;

    # we ask Nginx to ignore the Cache-Control header
    proxy_ignore_headers Cache-Control;

    # we cache any 200 or 302 response for up to 10 minutes
    proxy_cache_valid 200 302 10m;

    # any 404 response is cached for 1 minute
    proxy_cache_valid 404      1m;



Notes #

Cookies and cache #

For obvious reasons by default Nginx will not cache requests where the Set-Cookie header is set.

Unfortunately many server side technologies (PHP, Java etc) create a cookie based session with each request by default thus preventing Nginx from caching pretty much any request even if the Cache-Control header is set

In these circumstances it’s useful to setup a different cache punching header to send with not cacheable responses

# we ignore the Set-Cookie header
proxy_ignore_headers Set-Cookie;

# we hit origin every time a X-No-Cache custom header is set
proxy_no_cache $http_x_no_cache 

Invalidating the cache #

The opensource version of Nginx doesn’t come out of the box with many ways to invalidate the cache except proxy_cache_bypass

# Trigger a synchronous cache update 
# when a specific `X-No-Cache` header 
# or if a `nocache` GET parameter are set
proxy_cache_bypass $http_x_no_cache $arg_nocache;

Unfortunately proxy_cache_bypass does not update the internal cache reference if a 404 response code is returned

We have a few options


Now read this

Evolving CRUD (part 2)

Serving content at scale without complexity Command Querying Responsibility Segregation # Martin Fowler and Udi Dahan have in the past described this approach at length. This is obviously not a new concept and what follows is only a... Continue →