Last Updated: February 25, 2016
· alexzorin

nginx: Using fastcgi_cache with try_files rewrites

PHP-FPM and try_rewrite

Often with PHP-based applications you rewrite non-existent (on the filesystem, anyway) URLs to a script that performs routing, often index.php.

When using PHP-FPM, this often looks something like (incomplete example):

location / {
        try_files $uri $uri/ /index.php;
location ~ [^/]\.php(/|$) {
        fastcgi_index index.php;

Response Caching

fastcgi_cache is a great way to speed up cacheable pages, especially if you use a small tmpfs volume for storage.

Most online references approximately show you how to configure the cache:

# In an http{} block
# Cache HTTP 200s from PHP-FPM for 1 hour, 60mb cache in /var/cache/nginx/fastcgi_cache.
fastcgi_cache_valid 200 1h;
fastcgi_cache_path /var/cache/nginx/fastcgi_cache levels=1:2 keys_zone=DEFAULT:10m max_size=60m;
fastcgi_cache_key "$scheme$request_method$host$request_uri";
fastcgi_cache DEFAULT;

but not how to include/exclude from caching depending on the URI.

So ...

Cache inclusion and exclusion

If we wanted to cache /routeX (which would be served via index.php via our try_files directive), we would pass a map to fastcgi_cache_bypass:

# Still in the http{} block
# 0 is cacheable, otherwise bypass fastcgi_cache entirely
map $request_uri $no_cache {
        default 1;
        ~/routeX 0;
fastcgi_cache_bypass $no_cache;

The key here is to use $request_uri as the mapped variable rather than $uri. The latter is changed to index.php by try_files, which would mean the cache would always be bypassed!

For easier debugging, try add_header X-Cache $upstream_cache_status in your FastCGI location.