Skip to content
The Cloudflare Workers Playbook is out — read a free sample first.

Take WordPress to the edge with Cloudflare, without writing a plugin

Cache rules, a small Worker and early hints so WordPress serves 90% of requests from the edge — plus the traps that quietly break caching.

Published
10 June 2025
Read
2 min read
Written by
SSUSEMAN
Take WordPress to the edge with Cloudflare, without writing a plugin
edge — SUSEMANCloudflare · Workers

Most WordPress sites serve the same pages to almost everyone — yet we re-render them in PHP on every request. Cloudflare fixes that without touching your theme.

Start with your own traffic

Open Analytics and look at which paths consume requests. On my last audit, the top five paths were 78% of all requests, all of them static article pages.

A cache rule that is safe

Cache only GET requests without a login cookie, excluding admin and cart paths:

text
(http.request.method eq "GET"
 and not http.request.uri.path contains "/wp-admin"
 and not http.request.uri.path contains "/wp-login"
 and not http.request.uri.path contains "/cart"
 and not http.cookie contains "wordpress_logged_in"
 and not http.cookie contains "woocommerce_cart_hash")
-> Cache eligible, Edge TTL 1 hour, Browser TTL 10 minutes

A small Worker with outsized effect

Three jobs: strip noisy query parameters, add Early Hints, and serve a fallback when the origin is down.

js
export default {
  async fetch(request, env, ctx) {
    const url = new URL(request.url);
    ['fbclid', 'gclid', 'utm_source', 'utm_medium'].forEach((k) => url.searchParams.delete(k));

    const cacheKey = new Request(url.toString(), request);
    const cache = caches.default;

    let res = await cache.match(cacheKey);
    if (res) return res;

    res = await fetch(cacheKey, { cf: { cacheEverything: false } });
    if (res.ok) {
      const headers = new Headers(res.headers);
      headers.set('Cache-Control', 'public, max-age=600, s-maxage=3600');
      ctx.waitUntil(cache.put(cacheKey, new Response(res.body, { ...res, headers })));
    }
    return res;
  },
};

Early Hints from the origin

If the origin sends Link headers with a 103 Early Hints response, the browser starts fetching CSS and fonts before the HTML arrives. In production this bought 100–300ms of LCP.

apache
Header add Link "</wp-content/themes/suseman/style.css>; rel=preload; as=style"
Header add Link "</fonts/inter-var.woff2>; rel=preload; as=font; crossorigin"

Traps that silently break caching

  • Analytics plugin cookies make every request a cache miss. Scope the bypass rule.
  • Nonces in HTML: a cached checkout page hands users a stale nonce and the form fails.
  • Geo currency needs a Vary header or a country-keyed cache.
  • Forgetting to purge tag archives after publishing leaves stale pages for hours.

Always test: check cf-cache-status with curl -I while logged in and logged out. A HIT on the wrong page means your rule is too loose.

Outcome

On a Thai news site: 91% cache hit rate, 140ms average TTFB, 87% less origin load, and half the server bill.

S

Written by

SUSEMAN · Infrastructure engineer · Writer

A journal of cloud & web engineering · Bangkok, Thailand

About →

The weekly dispatch

New articles, tools worth testing and lessons from production — every Thursday. No spam, ever.

No spam. Unsubscribe anytime.

Related reading

View all →

Next article

Ingress vs egress: the GCP network bill that surprises everyone

→