How to purge the Nginx cache


When using the Nginx server as a caching server or reverse proxy server we have to think about refreshing the cached content. We have the topic for how to use Nginx as a reverse proxy, earlier. Let’s check out how we can purge the Nginx cache now.

If we look at the configuration of the Nginx we can see it stores cached responses on the path defined with the directive proxy_cache_path. In our example, it was on /var/cache/nginx. This information is important so we can plan and choose one of the available purge options:

  1. Manually or by-script deleting files from cache directory (in our case /var/cache/nginx)
  2. Purging with BYPASS method
  3. Using Nginx module proxy_cache_purge – available only with Nginx Plus (subscription required)

Purging with BYPASS method

This is one of two “free” options that do not require subscription or payments and yet, effective enough. Let’s first understand what BYPASS is. Directive proxy_cache_bypass is used to invalidate cache assets by instructing Nginx to pass the request back to the backend server and refresh the cached resource upon retrieval from the backend server. We are not deleting any cached item in the cache, rather we are refreshing it. In the real world, this behaviour is exactly what we need when handling the cache invalidation.

Nginx cache purge | BYPASS Method
Nginx cache purge | BYPASS Method

Let’s check out the configuration for this type of purge built on top of our configuration described here. What we need in order to make this purge type are following two blocks:

Lock purge from local ip only:

if ($remote_addr ~ "^(127.0.0.1)$") {
    set $bypass $http_cache_purge;
}

Call for BYPASS method if the request header Cache-Purge from the previous block is set:

proxy_cache_bypass $bypass;

Entire configuration file looks like this (Note that we have used a new origin server ip for test purposes):

proxy_cache_path /var/cache/nginx keys_zone=my_zone:10m inactive=10h;
server {
	listen 80 default_server;
	listen [::]:80 default_server;

  set $bypass 0;

  if ($remote_addr ~ "^(127.0.0.1)$") {
    set $bypass $http_cache_purge;
  }
root /var/www/html;
	index index.html index.htm index.nginx-debian.html;
 
	server_name _;
	proxy_cache_key $scheme$http_host$uri$is_args$args;
	location / {
        proxy_cache my_zone;
        proxy_pass http://138.68.74.185;
        proxy_cache_valid 200 1d;
        add_header Cache $upstream_cache_status;
        proxy_cache_min_uses 2;
        proxy_cache_bypass $bypass;
	}
}

Test BYPASS purge method

We will now test this method by invalidating the cached file on our test Nginx server. Before we invalidate it we’ll make sure that the origin file gets changed in order to confirm that Nginx took the fresh version and cached it.

  • Let’s first calculate MD5 Hash signature of the file already in cache:
$ curl localhost/index.html | md5sum 
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100  4057  100  4057    0     0   495k      0 --:--:-- --:--:-- --:--:--  565k
f483f4298e5a8cebc72d80166d4012ce  -
  • Now let’s make a change on the origin /index.html file. Change can be as small as even one letter. then we’ll calculate the MD5 on the origin server before we invalidate file in the Nginx cache:
$ curl localhost/index.html | md5sum 
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100  4059  100  4059    0     0   792k      0 --:--:-- --:--:-- --:--:--  792k
1c8c36b61e7e6a08054b8f14581d662e  -

Now we know what to expect on the Nginx side. Let’s send a new request for the Nginx version of this file with request header “Cache-Purge: true”:

curl localhost/index.html -H 'Cache-Purge: true' | md5sum 
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100  4059  100  4059    0     0   495k      0 --:--:-- --:--:-- --:--:--  495k
1c8c36b61e7e6a08054b8f14581d662e  -

Voila! We have successfully refreshed the Nginx cached file without proxy_cache_purge module nor, with manually deleting files in cache directory.

Not to be confused, when we look at headers we won’t see HIT or MISS on this kind request. We’ll see a BYPASS instead. That means that Nginx has bypassed the local cache and went straight to the backend server for the requested file. The result is that Nginx recached the same file, with new content, possibly:

curl localhost/index.html -H 'Cache-Purge: true' -I 
HTTP/1.1 200 OK
Server: nginx/1.14.1
Date: Thu, 06 Aug 2020 12:01:37 GMT
Content-Type: text/html
Content-Length: 4059
Connection: keep-alive
Last-Modified: Thu, 06 Aug 2020 11:56:10 GMT
ETag: "5f2befda-fdb"
Cache: BYPASS
Accept-Ranges: bytes

Manually purge Nginx cache

Ok, so ur cache directory is at /var/cache/nginx. This means that we can manually delete contents of this directory and the Nginx cache will be purged. A bit trivial approach but, it works if you are not using the Nginx Plus version.

Test manual Nginx purge method

  • Let’s first check out response header “Cache” for a file we already have in the cache:
curl -I http://bluegrid.io/index.html
HTTP/1.1 200 OK
Server: nginx/1.14.1
Date: Thu, 06 Aug 2020 12:12:08 GMT
Content-Type: text/html
Content-Length: 4059
Connection: keep-alive
Last-Modified: Thu, 06 Aug 2020 11:56:10 GMT
ETag: "5f2befda-fdb"
Cache: HIT
Accept-Ranges: bytes
  • Cache header has a value “HIT” meaning the file is cached. Now let’s purge Nginx cache manually:
$ sudo rm -rf /var/cache/nginx/*

Now, let’s check out Cache header value after above command:

curl -I http://bluegrid.io/index.html
HTTP/1.1 200 OK
Server: nginx/1.14.1
Date: Thu, 06 Aug 2020 12:14:58 GMT
Content-Type: text/html
Content-Length: 4059
Connection: keep-alive
Last-Modified: Thu, 06 Aug 2020 11:56:10 GMT
ETag: "5f2befda-fdb"
Cache: MISS
Accept-Ranges: bytes

Voila! The cache is purged as we can confirm by looking at the response header Cache showing a “MISS” value.

🧐 Why is this not the best option of purging the Nginx cache?

Well, for one, it requires manual action or script that would do this for us. Which is not that bad considering the ease of implementation of such script. The bigger problem is that this way of purging the Nginx cache deletes everything that was cached by this Nginx host. This is bad practice as it kills performance drastically on infrastructure with a high number of requests per time unit.

Purge the Nginx cache using proxy_cache_purge module

There is lots of documentation for this option and here is the link to official module documentation. This configuration is pretty straight forward and it goes something like this:

Map the $request_method from the request to a custom local variable we’ll call $cache_purge under the HTTP context:

http {
...
map $request_method $cache_purge {
        PURGE 1;
        default 0;
    }
}

Now call the purge action by using directive proxy_cache_purge like this:

location / {
        proxy_cache my_zone;
        proxy_pass http://138.68.74.185;
        proxy_cache_valid 200 1d;
        add_header Cache $upstream_cache_status;
        proxy_cache_min_uses 2;
        proxy_cache_purge $cache_purge;
	}

The full Nginx configuration file would look something like this:

proxy_cache_path /var/cache/nginx keys_zone=my_zone:10m inactive=10h;

map $request_method $cache_purge {
    PURGE 1;
    default 0;
}
server {
	listen 80 default_server;
	listen [::]:80 default_server;

  set $bypass 0;

  if ($remote_addr ~ "^(127.0.0.1)$") {
    set $bypass $http_cache_purge;
  }
root /var/www/html;
	index index.html index.htm index.nginx-debian.html;
 
	server_name _;
	proxy_cache_key $scheme$http_host$uri$is_args$args;
	location / {
        proxy_cache my_zone;
        proxy_pass http://138.68.74.185;
        proxy_cache_valid 200 1d;
        add_header Cache $upstream_cache_status;
        proxy_cache_min_uses 2;
        proxy_cache_purge $cache_purge;
	 }
}

Sending the purge request:

$ curl -X PURGE -D – "https://reverse.proxy/*"

That’s it!

Schedule a consultation
Share this post

Share this link via

Or copy link