Nginx FastCGI cache Configure Nginx FastCGI cache on a HolyCloud VPS to serve PHP pages from memory and reduce PHP-FPM load. ~11 min read Intermediate #nginx #fastcgi #cache #php Nginx FastCGI cache Nginx FastCGI cache stores PHP responses (HTML) on disk or in memory. On a HolyCloud Performance VPS, it drastically reduces PHP-FPM calls for cacheable public pages (home, articles, idempotent GET APIs). Prerequisites Nginx + PHP-FPM operational Understanding of Cache-Control headers and session cookies Disk space for the cache zone (/var/cache/nginx/fastcgi) Site where user-specific dynamic content is separated from public content Global cache zone In /etc/nginx/nginx.conf, http block: fastcgi_cache_path /var/cache/nginx/fastcgi levels=1:2 keys_zone=WORDPRESS:100m inactive=60m max_size=1g use_temp_path=off; Create the directory: sudo mkdir -p /var/cache/nginx/fastcgi sudo chown www-data:www-data /var/cache/nginx/fastcgi vhost configuration server { listen 443 ssl http2; server_name exemple.tld; root /var/www/exemple; set $skip_cache 0; # do not cache if session / admin if ($request_method = POST) { set $skip_cache 1; } if ($query_string != "") { set $skip_cache 1; } if ($request_uri ~* "/wp-admin/|/wp-login.php|/panier|/checkout") { set $skip_cache 1; } if ($http_cookie ~* "wordpress_logged_in|woocommerce_items_in_cart") { set $skip_cache 1; } location ~ \.php$ { include snippets/fastcgi-php.conf; fastcgi_pass unix:/run/php/php8.3-fpm.sock; fastcgi_cache WORDPRESS; fastcgi_cache_valid 200 301 302 60m; fastcgi_cache_valid 404 1m; fastcgi_cache_bypass $skip_cache; fastcgi_no_cache $skip_cache; fastcgi_cache_key "$scheme$request_method$host$request_uri"; add_header X-FastCGI-Cache $upstream_cache_status; } } Understanding X-FastCGI-Cache | Value | Meaning | |--------|----------------| | MISS | PHP executed, then stored | | HIT | Served from cache | | BYPASS | Cache skipped ($skip_cache rule) | | EXPIRED | Entry expired, recalculated | Test: curl -sI https://exemple.tld/ | grep X-FastCGI-Cache Two consecutive requests: MISS then HIT. Micro-cache for API For a public read API: fastcgi_cache_valid 200 10s; add_header Cache-Control "public, max-age=10"; Reduce inactive if data changes often. Manual purge Open-source Nginx has no native HTTP purge without a third-party module. File purge: sudo find /var/cache/nginx/fastcgi -type f -delete sudo nginx -s reload Automate after CMS deployment (CI hook). Stale cache (option) If PHP is unavailable, serve an expired version: fastcgi_cache_use_stale error timeout updating http_500 http_503; fastcgi_cache_background_update on; fastcgi_cache_lock on; Useful for resilience; watch for stale content. Verification and monitoring sudo nginx -t && sudo systemctl reload nginx du -sh /var/cache/nginx/fastcgi Logs: sudo tail -f /var/log/nginx/access.log | grep -E 'HIT|MISS' Common pitfalls WooCommerce cart: any cart cookie must bypass the cache. HTTPS mixed: key includes $scheme — OK. Comment moderation: pages with ?replytocom= query → exclude. RAM: keys_zone=100m ≈ 800k keys — adapt to traffic. Combined with PHP OPcache FastCGI cache ≠ OPcache: the first avoids running PHP; the second speeds execution. Use both. Need help? HolyCloud support: send sanitized nginx -T, curl -I headers, and CMS description if cache never activates (permanent BYPASS). Continue reading Previous article Monitoring with Netdata Read Next article Optimize NVMe disks Read