Site icon GetPageSpeed

Serve WP Rocket Cache Directly from Nginx Without PHP

Serve WP Rocket Cache Directly from Nginx Without PHP

Serve WP Rocket Cache Directly from Nginx Without PHP

WP Rocket writes cached pages as static HTML files. On a typical Nginx setup, a request still passes through PHP-FPM before that cached file reaches the visitor.

That extra hop is unnecessary. Nginx can locate and serve the existing WP Rocket cache file directly. PHP-FPM, WordPress, and the database stay out of the request.

WP Rocket Nginx is a small open-source WordPress plugin that generates the required Nginx configuration from the active WP Rocket settings. It does not replace WP Rocket. WP Rocket still creates and purges the cache. The plugin only teaches Nginx how to find those files safely.

Why bypass PHP for a static cache hit

A normal cached request can still travel through this path:

Nginx -> PHP-FPM -> PHP cache loader -> cached HTML file

With WP Rocket Nginx, the path becomes:

Nginx -> cached HTML file

The second path avoids starting a PHP worker for work Nginx already does well: checking a file and sending it to the client.

This matters most during traffic bursts. Direct cache hits do not occupy a limited PHP-FPM worker, leaving PHP capacity available for logged-in users, checkout requests, uncached pages, REST endpoints, and administrative work.

A conservative Nginx versus PHP-FPM benchmark

It would be easy to compare direct Nginx delivery with a full WordPress page render and publish a spectacular number. That would also be misleading.

The benchmark included with WP Rocket Nginx uses a stricter comparison. Both paths return the exact same 65,536-byte file:

There is no database query and no WordPress rendering on the PHP side. The test isolates the minimum overhead of involving PHP-FPM at all.

Test environment:

Median results across the five runs:

Path Requests/second p50 latency p95 latency
Nginx direct 1,151.3 12.91 ms 24.63 ms
PHP-FPM readfile() 786.9 16.12 ms 41.62 ms

In this local synthetic test, direct Nginx delivery produced:

These numbers are not a promise for every production server. Hardware, TLS, storage, PHP-FPM tuning, network latency, and concurrent workloads all matter. The useful conclusion is narrower: even a minimal PHP file-serving path has measurable overhead, while direct Nginx delivery preserves PHP workers for dynamic requests.

The complete benchmark is reproducible:

git clone https://github.com/dvershinin/wp-rocket-nginx.git
cd wp-rocket-nginx
make benchmark

The script verifies equal response bodies, HTTP status distributions, payload size, and request errors before reporting results.

Install WP Rocket Nginx

Download the current ZIP from the WP Rocket Nginx releases, then install and activate it as a normal WordPress plugin.

The plugin writes the generated configuration here by default:

wp-content/wp-rocket-nginx/default.conf

Include that file inside the website’s Nginx server block:

server {
    server_name example.com;
    root /var/www/example.com;

    include /var/www/example.com/wp-content/wp-rocket-nginx/default.conf;

    location / {
        try_files $uri $uri/ /index.php?$args;
    }

    # Existing PHP-FPM configuration follows.
}

Always validate the complete Nginx configuration before reloading it:

sudo nginx -t && sudo systemctl reload nginx

The plugin deliberately does not execute nginx or systemctl from PHP. A WordPress administrator should not gain permission to run server commands. Configuration generation happens in WordPress; validation and reload remain explicit server-operator actions.

Keep the generated configuration synchronized

WP Rocket Nginx reads the active WP Rocket options, including cached query strings, rejected cookies, HTTPS variants, and separate mobile cache files. It regenerates default.conf when those settings change.

Because Nginx loads configuration into memory, regeneration and reload are separate steps. After changing relevant WP Rocket settings:

sudo nginx -t && sudo systemctl reload nginx

The file is installed atomically. Nginx sees either the previous complete configuration or the new complete configuration, never a partially written file.

Verify direct cache hits

Enable diagnostic headers under Settings > WP Rocket Nginx, regenerate the file, validate Nginx, and reload it.

Then inspect a public cached page:

curl -I https://example.com/cached-page

A direct hit includes:

X-Rocket-Nginx-Serving-Static: HIT
X-Rocket-Nginx-Device: desktop

Other useful states are:

Diagnostic headers remain available on error responses, which helps distinguish a deliberate bypass from a missing file.

Query strings and separate mobile caches

Query strings are where cache configurations often become fragile. Tracking parameters such as utm_source can be ignored for cache lookup, while parameters explicitly cached by WP Rocket must map to the matching #argument directory.

Separate mobile cache files add another filename variant. The generated configuration calculates mobile markers from the normalized URI path and mapped arguments rather than the raw request URI. This includes regression coverage for the ?amp=1 mobile-cache failure reported in Rocket-Nginx issue #232.

The Docker E2E suite verifies desktop cache hits, ignored tracking parameters, unknown-query bypasses, authenticated-cookie bypasses, mobile query-string cache files, static assets, and protection of generated configuration files.

Serve static assets from Nginx too

The generated file includes direct Nginx locations for CSS, JavaScript, images, and fonts. Static files do not make a round trip through WordPress or PHP-FPM.

This is important beyond raw latency. Proxying static assets through an application consumes workers, repeats application logging and middleware, and can make asset traffic count against application-layer rate limits.

Remember WP-Cron

When Nginx serves most public traffic directly, those requests no longer start WordPress. They therefore do not trigger WordPress’ visit-driven pseudo-cron.

Disable visit-driven WP-Cron and run it from the system scheduler instead:

define( 'DISABLE_WP_CRON', true );

For example:

*/15 * * * * cd /var/www/example.com && php wp-cron.php >/dev/null 2>&1

Use the interval appropriate for the site and verify scheduled tasks after switching.

WP Rocket Nginx is open source

WP Rocket Nginx is released under the MIT License. Its Nginx template is derived from Rocket-Nginx 3.1.2 by Maxime Jobin and SatelliteWP, with attribution retained in the repository and distribution.

The project is unofficial and independent. WP Rocket is a trademark of WP Media.

If you run WP Rocket on a self-managed Nginx server, direct cache delivery is a small change with a clear operational benefit: fewer PHP-FPM requests for content that is already a static file.

D

Danila Vershinin

Founder & Lead Engineer

NGINX configuration and optimizationLinux system administrationWeb performance engineering

10+ years NGINX experience • Maintainer of GetPageSpeed RPM repository • Contributor to open-source NGINX modules

Exit mobile version