Cloudflare Workers can intercept every request before it reaches your WordPress origin, check a custom cache key in the Cloudflare Cache API, and serve a cached HTML response from the edge — reducing origin load to near zero for anonymous traffic. Unlike page-caching plugins that still hit PHP, Workers serve from CDN edge nodes globally with sub-millisecond latency.
The Worker below caches WordPress HTML responses for anonymous users, skips caching for logged-in users and WooCommerce cart pages, purges individual URLs on publish via a WordPress hook, and passes cache-status headers for debugging.
// Cloudflare Worker: wp-edge-cache.js
const CACHE_TTL = 3600; // 1 hour for regular pages
const BYPASS_PATHS = [ '/wp-admin', '/wp-login', '/cart', '/checkout', '/my-account' ];
const BYPASS_PARAMS = [ 'preview', 's', 'p', 'page_id' ];
export default {
async fetch( request, env, ctx ) {
const url = new URL( request.url );
const cache = caches.default;
// ── Bypass conditions ───────────────────────────────────────────
const shouldBypass =
request.method !== 'GET'
|| BYPASS_PATHS.some( p => url.pathname.startsWith( p ) )
|| BYPASS_PARAMS.some( p => url.searchParams.has( p ) )
|| ( request.headers.get( 'Cookie' ) || '' ).includes( 'wordpress_logged_in' )
|| ( request.headers.get( 'Cookie' ) || '' ).includes( 'woocommerce_items_in_cart' );
if ( shouldBypass ) {
const resp = await fetch( request );
return new Response( resp.body, {
...resp,
headers: { ...Object.fromEntries( resp.headers ), 'x-cache': 'BYPASS' },
} );
}
// ── Check cache ─────────────────────────────────────────────────
const cacheKey = new Request( url.toString(), { method: 'GET' } );
let response = await cache.match( cacheKey );
if ( response ) {
return new Response( response.body, {
...response,
headers: { ...Object.fromEntries( response.headers ), 'x-cache': 'HIT' },
} );
}
// ── Cache miss: fetch from origin ───────────────────────────────
const originResponse = await fetch( request );
if ( originResponse.status === 200
&& ( originResponse.headers.get( 'content-type' ) || '' ).includes( 'text/html' )
) {
const responseToCache = new Response( originResponse.body, {
...originResponse,
headers: {
...Object.fromEntries( originResponse.headers ),
'Cache-Control': `public, max-age=${CACHE_TTL}`,
'x-cache': 'MISS',
},
} );
ctx.waitUntil( cache.put( cacheKey, responseToCache.clone() ) );
return responseToCache;
}
return originResponse;
},
};
[
'Authorization' => "Bearer $cf_token",
'Content-Type' => 'application/json',
],
'body' => wp_json_encode( [ 'files' => [ $url ] ] ),
]
);
} );
NOTE: The caches.default Cache API in Cloudflare Workers is shared across all Workers in your zone — cache keys are the full URL including query string; ensure your bypass logic strips or normalises UTM parameters and other tracking query strings before using the URL as a cache key, or cache entries will be created for every unique UTM combination.