A client called me last week. His e-commerce site was crawling, not just slow but genuinely crawling. “Ahmad,” he said, “we’ve got caching plugins and the server’s decent, but every time traffic spikes the whole thing chokes.” That is usually what happens when WordPress page caching with a CDN isn’t set up right.
WordPress, by its very nature, is dynamic. Every visit, every page load for a non-logged-in user, still triggers PHP and hits the database. Your server-side caching can only do so much. It stores generated HTML, sure, but it’s still serving that from your origin. For local traffic, that’s often fine. But when your audience is global, latency becomes a monster.
When I started out, like a lot of devs, my instinct was always to optimize database queries, minify CSS, and compress images. Those things matter, and you can’t slap a cache on a broken site and expect miracles. But for years I missed the bigger picture. I kept seeing sites with global audiences struggle even with clean code. The problem was the distance between the user and the server, plus the constant load on the origin for pages that should have been static.
What CDN full page caching actually does
This is where CDN for WordPress performance goes beyond basic server caching. It isn’t only about static assets like images and scripts, though that’s the baseline. The CDN caches the entire HTML page at its edge locations. When someone requests a page that’s already cached on the nearest edge server, the request never touches your WordPress origin at all. Users get faster loads and your server gets a real break.
There’s a catch, though: invalidation. WordPress isn’t a static site. Content changes constantly as products get updated, posts get published, and comments come in, so you can’t cache a page forever. You need a way to tell the CDN when a cached page has gone stale and should be purged and refetched from your origin. In practice that means setting sensible
Cache-Control and
Expires headers and usually hooking into your CDN’s API to trigger purges when content changes. Carl Alexander has written about this exact problem over at carlalexander.ca.
Most modern CDNs let you configure rules for this. You bypass the cache entirely for logged-in users (anyone carrying the
wordpress_logged_in_ cookies) and for
/wp-admin/ paths, and you cache aggressively for everyone else, which is the bulk of your traffic. The example below shows roughly how a CDN-aware plugin or a bit of custom code might set
Cache-Control headers in
functions.php. Real setups are more involved and talk to a CDN API, but the shape is the same:
<?php
add_action( 'template_redirect', function() {
if ( is_user_logged_in() || is_admin() || is_cart() || is_checkout() ) {
header( 'Cache-Control: no-store, no-cache, must-revalidate, max-age=0' );
header( 'Pragma: no-cache' );
header( 'Expires: Fri, 01 Jan 1990 00:00:00 GMT' );
} else {
// Cache for 1 hour at CDN edge
header( 'Cache-Control: public, max-age=3600, s-maxage=3600' );
}
});
// Example: Purge a specific URL from CDN on post update (requires CDN API integration)
function my_cdn_purge_post( $post_id ) {
// Only purge if it's a public post type
if ( get_post_status( $post_id ) === 'publish' ) {
$url = get_permalink( $post_id );
// Call CDN API here to purge $url
// e.g., my_cdn_api_call_to_purge( $url );
}
}
add_action( 'save_post', 'my_cdn_purge_post' );
?>
The
s-maxage value in that
Cache-Control header is the one that matters for CDNs. It tells shared caches how long to hold the page, while
max-age covers private browser caches. Skip the invalidation part and you’ll end up serving stale content, which is exactly the kind of thing that gets you an angry call from a client.
What this actually gets you
- Serve cached pages straight from the edge so your origin server handles far fewer requests.
- Reach users faster wherever they are, since the CDN’s servers are spread around the world.
- Set rules that skip the cache for dynamic, user-specific pages like carts and checkouts while caching everything static.
- Keep a solid invalidation strategy so what you serve from the edge stays current.
This stuff gets complicated fast. If you’re tired of debugging someone else’s mess and just want the site to work, drop my team a line. We’ve probably seen it before.
I'm a WordPress and WooCommerce developer with 15+ years of experience building custom e-commerce solutions and plugins. I specialize in PHP development, following WordPress coding standards to deliver clean, maintainable code. Currently, I'm exploring AI and e-commerce by building multi-agent systems and SaaS products that integrate technologies like Google Gemini API with WordPress platforms, approaching every project with a commitment to performance, security, and exceptional user experience.