Skip to Content
Frontlane Studio
All Snippets
PHP Performance November 5, 2025

Edge Cache Headers for WordPress on Cloudflare

Set aggressive cache-control headers for static assets and fine-tune TTLs for HTML to get the most out of Cloudflare's edge network.

WordPress Cloudflare Caching

Getting the most out of Cloudflare’s cache means sending the right Cache-Control headers from your origin. WordPress doesn’t do this by default — it either sends no-cache or nothing at all. Drop this into your theme’s functions.php or a must-use plugin.

<?php
/**
 * Set edge-friendly Cache-Control headers.
 * - Static logged-out pages: cache at edge for 1 hour, stale-while-revalidate 5 min
 * - Logged-in users: bypass cache entirely
 * - WooCommerce cart/checkout: always private
 */
add_action( 'send_headers', function () {
    // Never cache for logged-in users
    if ( is_user_logged_in() ) {
        header( 'Cache-Control: no-store, private' );
        return;
    }

    // Never cache WooCommerce dynamic pages
    if ( function_exists( 'is_woocommerce' ) ) {
        if ( is_cart() || is_checkout() || is_account_page() ) {
            header( 'Cache-Control: no-store, private' );
            return;
        }
    }

    // Cache everything else at the edge
    header( 'Cache-Control: public, max-age=3600, stale-while-revalidate=300, stale-if-error=86400' );
} );

Paired Cloudflare Cache Rule

In your Cloudflare dashboard, create a Cache Rule that matches your hostname and sets Cache Status to Cache Everything. The Cache-Control header above will govern TTLs — Cloudflare respects max-age when this rule is active.

Purging on publish

Pair this with a publish hook to purge the Cloudflare cache when a post is updated:

add_action( 'save_post', function ( $post_id ) {
    if ( wp_is_post_revision( $post_id ) ) return;

    $zone_id = defined( 'CF_ZONE_ID' ) ? CF_ZONE_ID : '';
    $token   = defined( 'CF_API_TOKEN' ) ? CF_API_TOKEN : '';

    if ( ! $zone_id || ! $token ) return;

    wp_remote_post(
        "https://api.cloudflare.com/client/v4/zones/{$zone_id}/purge_cache",
        [
            'headers' => [
                'Authorization' => "Bearer {$token}",
                'Content-Type'  => 'application/json',
            ],
            'body' => wp_json_encode( [ 'purge_everything' => true ] ),
        ]
    );
} );

Define CF_ZONE_ID and CF_API_TOKEN as constants in wp-config.php, never hardcoded.