Back to Top

Nginx FastCGI Cache on Magento 2 with PHP-FPM

Updated 15 April 2026

Configuring Nginx FastCGI Cache on Magento 2 is one of the most effective ways to improve your store’s page speed and reduce server load. This guide covers the complete Nginx FastCGI Cache Magento 2 setup with PHP-FPM — no additional software or reverse proxy required. Nginx builds FastCGI cache directly and stores the HTML output that PHP generates serving repeat requests instantly without invoking PHP or querying the database.

Without Nginx FastCGI Cache
Browser → Nginx → PHP-FPM → Magento 2 → Database
every request runs PHP and hits the database – slow under load

With Nginx FastCGI Cache (HIT)
Browser → Nginx → FastCGI Cache → Response
zero PHP, zero database – instant response for every guest visitor

Prerequisites

Before setting up Nginx FastCGI Cache on Magento 2, ensure the following are in place on your server:

  • Ubuntu 20.04 / 22.04 / 24.04
  • Nginx 1.18 or higher
  • PHP 8.1 / 8.2 / 8.3 / 8.4 with PHP-FPM installed
  • Magento 2.4.x installed and running
  • Root or sudo access to the server

Configure PHP-FPM Pool

PHP-FPM runs as a separate process that Nginx communicates with. First, install PHP-FPM with all extensions required by Magento 2:

sudo apt update
sudo apt install php8.3-fpm php8.3-mysql php8.3-xml php8.3-curl \
    php8.3-gd php8.3-mbstring php8.3-intl php8.3-bcmath \
    php8.3-soap php8.3-zip php8.3-xsl -y

Create a dedicated Magento PHP-FPM pool configuration:

sudo nano /etc/php/8.3/fpm/pool.d/magento.conf
[magento]
user  = www-data
group = www-data

; TCP socket — matches the Nginx upstream directive
listen = 127.0.0.1:9000

pm                   = dynamic
pm.max_children      = 20
pm.start_servers     = 5
pm.min_spare_servers = 3
pm.max_spare_servers = 10
pm.max_requests      = 500

php_admin_value[memory_limit]        = 756M
php_admin_value[max_execution_time]  = 600
php_admin_value[upload_max_filesize] = 64M
php_admin_value[post_max_size]       = 64M
php_admin_flag[log_errors]           = on

; OPcache — strongly recommended for Magento 2 performance
php_admin_value[opcache.memory_consumption]    = 512
php_admin_value[opcache.max_accelerated_files] = 60000

; Sessions
php_value[session.save_handler] = files
php_value[session.save_path]    = /var/www/html/magento/var/session

Enable and start PHP-FPM:

Start your headless eCommerce
now.
Find out More
sudo systemctl enable php8.3-fpm
sudo systemctl start php8.3-fpm

Configure Nginx FastCGI Cache on Magento 2

The Nginx FastCGI Cache zone is defined inside the http { } block of /etc/nginx/nginx.conf. This allocates shared memory for cache keys and sets the disk path where Nginx stores cached responses.

sudo nano /etc/nginx/nginx.conf

Add the following inside the http { } block:

# ── Nginx FastCGI Cache Zone for Magento 2 ───────────────────────────
# keys_zone=magento_cache:256m  → 256MB RAM for cache index
# inactive=1d                   → remove cache unused for 1 day
# max_size=10g                  → max 10GB disk cache
fastcgi_cache_path /var/cache/nginx/magento_fastcgi_cache
                   levels=1:2
                   keys_zone=magento_cache:256m
                   inactive=1d
                   max_size=10g;

fastcgi_cache_key "$scheme$request_method$host$request_uri";
fastcgi_cache_use_stale error timeout invalid_header http_500;
fastcgi_ignore_headers  Cache-Control Expires Set-Cookie;

; Buffer sizes — required for Magento 2 large response headers
fastcgi_buffers         16 16k;
fastcgi_buffer_size     32k;
proxy_buffer_size       128k;
proxy_buffers           4 256k;
proxy_busy_buffers_size 256k;

Create the cache directory and set permissions:

sudo mkdir -p /var/cache/nginx/magento_fastcgi_cache
sudo chown -R www-data:www-data /var/cache/nginx

Configure Magento 2 Nginx Server Block

Create the Nginx server block for Magento 2. This file defines the FastCGI cache bypass rules, static file handling, and the PHP-FPM upstream connection.

sudo nano /etc/nginx/conf.d/magento.conf
upstream fastcgi_backend {
    server 127.0.0.1:9000;
    keepalive 32;
}

server {
    listen 80;
    server_name yourdomain.com;

    set $MAGE_ROOT /var/www/html/magento;
    root $MAGE_ROOT/pub;
    index index.php;
    autoindex off;
    charset UTF-8;

    # ── FastCGI Cache Bypass Rules ────────────────────────────────────
    set $no_cache 0;

    # Never cache POST requests
    if ($request_method = POST)  { set $no_cache 1; }

    # Never cache URLs with query strings
    if ($query_string != "")     { set $no_cache 1; }

    # Never cache admin, checkout, cart, account, or API pages
    if ($request_uri ~* "/(admin|adminhtml|checkout|cart|account|rest|graphql)") {
        set $no_cache 1;
    }

    # Never cache requests from logged-in users
    if ($http_cookie ~* "PHPSESSID|admin_user|customer_logged_in|adminhtml") {
        set $no_cache 1;
    }

    # ── Security Headers ──────────────────────────────────────────────
    add_header X-Frame-Options        "SAMEORIGIN";
    add_header X-XSS-Protection       "1; mode=block";
    add_header X-Content-Type-Options "nosniff";

    # ── Static Files — served by Nginx directly (no PHP needed) ──────
    location /static/ {
        expires max;
        add_header Cache-Control "public";
        location ~ ^/static/version\d*/ {
            rewrite ^/static/version\d*/(.*)$ /static/$1 last;
        }
        if (!-f $request_filename) {
            rewrite ^/static/(version\d*/)?(.*)$ /static.php?resource=$2 last;
        }
    }

    location /media/ {
        try_files $uri $uri/ /get.php$is_args$args;
    }

    # ── PHP-FPM with Nginx FastCGI Cache ─────────────────────────────
    location ~ ^/(index|get|static|errors/report|errors/404|errors/503|print)\.php$ {
        try_files $uri =404;

        fastcgi_pass            fastcgi_backend;
        fastcgi_index           index.php;
        fastcgi_param           SCRIPT_FILENAME $document_root$fastcgi_script_name;
        fastcgi_param           PHP_VALUE "memory_limit=756M \n max_execution_time=600";
        fastcgi_read_timeout    600s;
        fastcgi_connect_timeout 600s;
        include                 fastcgi_params;

        # Nginx FastCGI Cache directives
        fastcgi_cache           magento_cache;
        fastcgi_cache_valid 200 301 302  1h;   # cache hits for 1 hour
        fastcgi_cache_valid 404          1m;   # cache 404s for 1 minute
        fastcgi_cache_bypass    $no_cache;
        fastcgi_no_cache        $no_cache;

        # Shows HIT / MISS / BYPASS in response headers
        add_header X-FastCGI-Cache $upstream_cache_status;
    }

    # ── Magento 2 Front Controller ────────────────────────────────────
    location / {
        try_files $uri $uri/ /index.php$is_args$args;
    }

    # ── Deny Sensitive Files ──────────────────────────────────────────
    location ~* (\.php$|\.htaccess$|\.git) { deny all; }
    location ~ /\.                          { deny all; }
}

Set File Permissions

Correct file permissions allow Magento 2 to write cache, session, and generated files without errors:

# Set ownership
sudo chown -R www-data:www-data /var/www/html/magento

# Magento 2 writable directories
sudo chmod -R 775 /var/www/html/magento/var \
                  /var/www/html/magento/generated \
                  /var/www/html/magento/pub/static \
                  /var/www/html/magento/pub/media \
                  /var/www/html/magento/app/etc

# Make Magento CLI executable
sudo chmod +x /var/www/html/magento/bin/magento

Test the Configuration

Validate and Restart Services

sudo nginx -t
sudo systemctl restart nginx
sudo systemctl restart php8.3-fpm

A successful validation shows:

nginx: configuration file /etc/nginx/nginx.conf test is successful

Verify Nginx FastCGI Cache is Working

Use curl to check the X-FastCGI-Cache response header:

# First request — cache is empty
curl -I http://yourdomain.com | grep X-FastCGI-Cache
# X-FastCGI-Cache: MISS

# Second request — served from Nginx FastCGI Cache
curl -I http://yourdomain.com | grep X-FastCGI-Cache
# X-FastCGI-Cache: HIT ⚡

Note: X-FastCGI-Cache: HIT confirms that Nginx FastCGI Cache on Magento 2 is working correctly — PHP-FPM and the database played no role in serving the response.

Confirm Cache Files on Disk

ls -la /var/cache/nginx/magento_fastcgi_cache/

Each file in this directory represents one cached Magento 2 page response stored on disk.

Flush the Nginx FastCGI Cache

There are several ways to flush the Nginx FastCGI Cache on your Magento 2 store.

Full Flush — Delete All Cache Files

sudo rm -rf /var/cache/nginx/magento_fastcgi_cache/*

Flush Magento 2 + Nginx FastCGI Cache Together

php /var/www/html/magento/bin/magento cache:flush
sudo rm -rf /var/cache/nginx/magento_fastcgi_cache/*

Reusable Flush Script

Save as flush-cache.sh and run it after every deployment:

#!/bin/bash
echo "Flushing Magento 2 cache..."
php /var/www/html/magento/bin/magento cache:flush

echo "Flushing Nginx FastCGI Cache..."
sudo rm -rf /var/cache/nginx/magento_fastcgi_cache/*

echo "✅ All caches flushed successfully!"
chmod +x flush-cache.sh
./flush-cache.sh

Important: Always flush both the Magento 2 cache and the Nginx FastCGI Cache after deploying code changes, running setup:upgrade, or deploying static content. Stale cache can cause your visitors to see outdated pages.

Nginx FastCGI Cache Status Reference

Every Nginx response includes an X-FastCGI-Cache header. Here is what each status value means for your Magento 2 store:

StatusMeaningPHP Called?DB Called?
HITServed directly from Nginx FastCGI Cache ⚡❌ No❌ No
MISSCache was empty — PHP processed and stored the response✅ Yes✅ Yes
BYPASSCache skipped — admin, checkout, cart, or logged-in user✅ Yes✅ Yes
EXPIREDCached entry expired and is being refreshed by PHP-FPM✅ Yes✅ Yes

What Nginx FastCGI Cache Serves on Magento 2

HomepageHITGuest visitor, no session cookie
Category pagesHITGuest visitor, no session cookie
Product pagesHITGuest visitor, no session cookie
CMS pagesHITGuest visitor, no session cookie
Admin panelBYPASSURL rule — /admin
Checkout / CartBYPASSURL rule — /checkout
Customer accountBYPASSSession cookie detected
REST API / GraphQLBYPASSURL rule — /rest, /graphql

Conclusion

Configuring Nginx FastCGI Cache on Magento 2 with PHP-FPM is one of the simplest and most impactful performance improvements for any Magento 2 store. The setup requires no additional software — FastCGI cache is built directly into Nginx — and dramatically reduces server load and response times under real traffic.

With Nginx FastCGI Cache in place, Nginx serves guest-facing pages such as the homepage, category pages, and product pages with zero PHP execution and zero database queries. At the same time, bypass rules ensure that PHP-FPM always processes the admin panel, checkout, cart, and logged-in customer sessions fresh, maintaining full Magento 2 functionality.

For further Magento 2 performance improvements, consider combining Nginx FastCGI Cache with Redis for session and cache storage, and OpenSearch for catalog search.

For official documentation, refer to the Nginx caching guide.

. . .

Leave a Comment

Your email address will not be published. Required fields are marked*


Be the first to comment.

Back to Top

Message Sent!

If you have more details or questions, you can reply to the received confirmation email.

Back to Home