Skip to content

💾 Caching Configuration

Static File Caching

nginx
server {
    # Force cache static assets for 30 days (for hashed filenames)
    location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg|woff2)$ {
        expires 30d;
        add_header Cache-Control "public, immutable";

        # Disable access logging (reduces I/O)
        access_log off;
    }

    # HTML files — no caching (ensures users always get the latest version)
    location ~* \.html$ {
        expires -1;
        add_header Cache-Control "no-cache, no-store, must-revalidate";
    }

    # Custom 404 page
    error_page 404 /404.html;
    location = /404.html {
        internal;
        root /var/www/errors;
    }
}

Proxy Cache

For reverse proxy scenarios, Nginx can cache backend responses to reduce backend load. Ideal for content that doesn't change frequently.

nginx
http {
    # Define cache zone (100MB memory + 10GB disk)
    proxy_cache_path /var/cache/nginx levels=1:2
      keys_zone=my_cache:100m
      max_size=10g
      inactive=60m
      use_temp_path=off;

    server {
        location /api/ {
            proxy_pass http://backend;

            # Enable caching
            proxy_cache my_cache;

            # Cache key (differentiated by URI + query parameters)
            proxy_cache_key "$scheme$request_method$host$request_uri";

            # Cache duration (default when backend doesn't set Cache-Control)
            proxy_cache_valid 200 302 10m;
            proxy_cache_valid 404 1m;

            # Cache lock — prevents cache stampede (multiple requests hitting backend simultaneously)
            proxy_cache_lock on;
            proxy_cache_lock_timeout 5s;

            # Add cache status header (useful for debugging)
            add_header X-Cache-Status $upstream_cache_status;

            # Backend custom cache control
            proxy_cache_bypass $http_cache_control;
        }
    }
}
bash
# Verify if caching is working
curl -I http://example.com/api/data
HTTP/1.1 200 OK
X-Cache-Status: HIT cache hit
...
X-Cache-Status: MISS cache miss (first access)
X-Cache-Status: EXPIRED cache expired
X-Cache-Status: BYPASS cache bypassed

# Clear cache
rm -rf /var/cache/nginx/*
# Or use the proxy_cache_purge module (requires compilation)

FastCGI Cache (PHP)

nginx
http {
    # Cache for PHP-FPM scenarios
    fastcgi_cache_path /var/cache/nginx/fastcgi
      levels=1:2
      keys_zone=php_cache:64m
      max_size=1g
      inactive=60m;

    server {
        location ~ \.php$ {
            fastcgi_pass unix:/run/php/php8.2-fpm.sock;
            fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
            include fastcgi_params;

            # Enable FastCGI cache
            fastcgi_cache php_cache;
            fastcgi_cache_valid 200 5m;
            fastcgi_cache_key "$scheme$request_method$host$request_uri";
            add_header X-Cache-Status $upstream_cache_status;
        }
    }
}