The Bottleneck: Uncached WordPress REST API Endpoints

When running headless WordPress or mobile applications powered by the WordPress REST API (/wp-json/wp/v2/), uncached JSON queries frequently overwhelm MySQL database pools. While standard HTML pages can easily be cached by standard CDN page rules, REST API requests often feature query parameters, pagination, and dynamic headers that result in frequent cache misses at the edge.

In this technical implementation guide, Saizul Amin demonstrates how to deploy a high-speed Edge Caching layer using Cloudflare Workers and KV to serve WordPress API endpoints in under 25 milliseconds globally.

Edge Caching Architecture Overview

Rather than forwarding every REST API request directly to PHP-FPM, a Cloudflare Worker intercepts requests at Cloudflare’\”s nearest edge data center. The worker inspects the request signature, queries Cloudflare KV or Cache API, and instantly responds from RAM/SSD cache. On WordPress content updates, a webhook triggers programmatic cache invalidation.

Metric Direct Origin (PHP-FPM + MySQL) Cloudflare Edge Cache + Workers Performance Gain
Time to First Byte (TTFB) 280ms – 750ms 18ms – 35ms 15x – 25x Faster
Origin CPU Utilization 85% under 500 req/sec load < 3% under 500 req/sec load 96% Server Offload
Cache Hit Ratio 45% (standard edge rules) 97.8% (normalized Worker KV) +52.8% Hit Rate

Cloudflare Worker Script: Normalized REST Cache

Deploy the following TypeScript worker script to handle endpoint caching, parameter sorting (to maximize cache hit rates), and stale-while-revalidate headers:


export default {
  async fetch(request: Request, env: any, ctx: ExecutionContext): Promise<Response> {
    const url = new URL(request.url);

    // Only intercept WordPress REST API GET requests
    if (request.method !== '\''GET'\'' || !url.pathname.startsWith('\''/wp-json/'\'')) {
      return fetch(request);
    }

    // Normalize URL search parameters to prevent cache duplication
    url.searchParams.sort();
    const cacheKey = new Request(url.toString(), request);
    const cache = caches.default;

    // Check Cloudflare Edge Cache
    let response = await cache.match(cacheKey);
    if (response) {
      const cachedHeaders = new Headers(response.headers);
      cachedHeaders.set('\''X-Edge-Cache'\'', '\''HIT-CLOUDFLARE'\'');
      return new Response(response.body, {
        status: response.status,
        headers: cachedHeaders
      });
    }

    // Fetch from WordPress Origin Server
    const originResponse = await fetch(request);

    // Only cache successful 200 OK responses
    if (originResponse.status === 200) {
      const responseToCache = new Response(originResponse.body, originResponse);
      responseToCache.headers.set('\''Cache-Control'\'', '\''public, max-age=3600, s-maxage=86400, stale-while-revalidate=600'\'');
      responseToCache.headers.set('\''X-Edge-Cache'\'', '\''MISS-SAVED'\'');

      // Asynchronously store in Cloudflare Edge Cache
      ctx.waitUntil(cache.put(cacheKey, responseToCache.clone()));
      return responseToCache;
    }

    return originResponse;
  }
};

Automated Cache Purge via WordPress Webhook

To ensure content stays fresh when editors publish or update posts, add a lightweight action hook in your WordPress theme’\”s functions.php or custom plugin:


add_action('\''save_post'\'', '\''purge_cloudflare_rest_cache'\'', 10, 3);
function purge_cloudflare_rest_cache($post_id, $post, $update) {
    if (wp_is_post_revision($post_id) || $post->post_status !== '\''publish'\'') {
        return;
    }

    $cloudflare_zone = '\''YOUR_ZONE_ID'\'';
    $cloudflare_token = '\''YOUR_PURGE_API_TOKEN'\'';

    $url = "https://api.cloudflare.com/client/v4/zones/{$cloudflare_zone}/purge_cache";
    
    // Purge specific tags or entire REST API prefix
    $body = json_encode([
        '\''prefixes'\'' => [
            home_url('\''/wp-json/wp/v2/posts'\'')
        ]
    ]);

    wp_remote_post($url, [
        '\''headers'\'' => [
            '\''Authorization'\'' => '\''Bearer '\'' . $cloudflare_token,
            '\''Content-Type'\''  => '\''application/json'\''
        ],
        '\''body'\''    => $body,
        '\''timeout'\'' => 5
    ]);
}

Security & Cache Segmentation

Always verify that sensitive endpoints (e.g., /wp-json/wp/v2/users/me or endpoints containing Authorization headers) are explicitly bypassed in the worker logic. Storing authenticated user sessions in public edge cache creates critical privacy leaks.

NEW BLOGS. REAL STRATEGIES. REAL RESULTS.

Join our community and receive powerful SEO tips, web optimization guides, and growth strategies as soon as they’re published.

Don’t just read blogs — stay ahead of the competition.

We don’t spam! Read our privacy policy for more info.

Share.
Leave A Reply