Transparent cache in Nginx


Let's assume you have website that is regulary occures under Slashdot effect. We should perpare it for highload.

Starting from 0.8.46 nginx has some options to enable transparent cache. Transparent for every visitor, in other words this cache if effective until user is not logged in. This options will help servier be live when user visits are rapidly grown. To acquire this feture you should disable session autostart.

Disable session autostart

For PHP you should edit you php.ini file or virtual host configuration and set name for session cookie

php_admin_value "session"
php_admin_value session.auto_start 0

If your website start session itself you should replace sessioin_start() function call with something like the following:

if (!empty($_COOKIE[session_name()]) || $_SERVER['REQUEST_METHOD'] == 'POST') {
	session_id() || session_start();

This makes sessioin start only if:

  • session cookie already set
  • login/pass form is sent

Seting up Nginx to cache without session cookie

After we disabled our website to initiate session each time we should configure Nginx for transparent caching. To do this add the following lines in virtual host configuration before server block:

proxy_cache_path /var/lib/nginx/cache levels=1:2 keys_zone=cache:30m max_size=1G;
proxy_temp_path /var/lib/nginx/proxy 1 2;
proxy_ignore_headers Expires Cache-Control;
proxy_cache_use_stale error timeout invalid_header http_502;
proxy_cache_bypass $cookie_session;
proxy_no_cache $cookie_session;

And don't forget to prepare necessary directories:

$sudo mkdir -p  /var/lib/nginx/cache
$sudo chown -R www-data /var/lib/nginx/cache
$sudo chmod 700 /var/lib/nginx/cache

Now let's enable caching for website:

location / {
	proxy_cache cache;
	proxy_cache_valid 10m;
	proxy_cache_valid 404 1m;
	proxy_pass http://backend;

Restart Nginx, clear browser cookies and test !

Some tweaks

You can set cache time with the following option:

header("X-Accel-Expires: $seconds");

So to completely disable cache set seconds to 0:

header("X-Accel-Expires: 0");


Lets test our configuration with the following command:

ab -n 1000 -c 100

With transparent caching my test website processed 100 rps with ease, without it got down on 70% of queries

Force cache renew

if you set the following option:

proxy_cache_bypass $cookie_session $http_x_update;

You can renew cache with the following command:

curl -H "X-Update: 1"


This article was originally translated from this source: [RU]