Developer Reference

Everything you need to configure, extend, and control FrostyCache through code.

Section Reference
OverviewHow FrostyCache works, cache storage, skip parameter
ConstantsFROSTYCACHE_AGE, FROSTYCACHE_REST_PREFIX, FROSTYCACHE_FOLDER
Filters14 filters for cache duration, skip logic, keys, headers, ETags, and more
Actions6 actions for cache save, delete, and clear lifecycle events
WP-CLIflush, clear-post, clear-route, clear-index, status, cleanup, warm, repair, license, rollback

Overview

FrostyCache caches WordPress REST API GET responses as static JSON files and serves them before the database loads. Configuration is done entirely through PHP filters, constants, and WP-CLI commands.

Cache files are stored in wp-content/uploads/frostycache_cache/. Each cached response includes the JSON data, response headers, an ETag, and an absolute expiry timestamp written at save time. Logged-in users and nonce-bearing requests bypass the cache by default.

Add ?skip_cache=1 to any REST API request to force a fresh response.

Constants

Define these in wp-config.php to override defaults.

FROSTYCACHE_AGE

Cache expiration in seconds. Default: 86400 (1 day). Sets the global default; can be overridden per request with the frostycache_cache_age filter. The duration in effect is stored in each cache file as an absolute expiry at save time, so changing this value only affects newly cached responses — flush the cache to apply it to existing files.

Define in wp-config.php before FrostyCache loads.

FROSTYCACHE_REST_PREFIX

REST API URL prefix. Default: /wp-json. Override if you use a custom REST prefix.

FROSTYCACHE_FOLDER

Cache directory path. Default: wp-content/uploads/frostycache_cache/. Automatically uses per-site directories on multisite.

Filters

frostycache_cache_age

Filter

Control cache duration per request. Return an array with length and period keys. The default is FROSTYCACHE_AGE if defined, otherwise 1 day. The resulting duration is stored in the cache file as an absolute expiry at save time, so per-route durations are honored by every layer — including the early-serve drop-in / MU plugin and the expired-file cleanup cron. Changing a duration only affects newly cached responses; flush the cache to apply it to existing files.

Example: 1-hour cache for product endpoints
add_filter( ‘frostycache_cache_age’, function( $cache_age, $request ) { if ( str_contains( $request->get_route(), ‘/products’ ) ) { return [ ‘length’ => 1, ‘period’ => HOUR_IN_SECONDS ]; } return $cache_age; }, 10, 2 );

frostycache_skip_cache

Filter

Decide whether a request should skip caching entirely. Return true to bypass.

Example: Skip caching for a private namespace
add_filter( ‘frostycache_skip_cache’, function( $skip, $request ) { if ( str_contains( $request->get_route(), ‘/myapp/v1/private’ ) ) { return true; } return $skip; }, 10, 2 );

frostycache_skip_cache_nonce

Filter

Control whether requests containing a nonce header bypass caching. Default: true (skip).

Example: Allow caching even with nonces
add_filter( ‘frostycache_skip_cache_nonce’, ‘__return_false’ );

frostycache_dangerous_routes

Filter

Define REST API routes that should never be cached.

Example: Add a custom route to the blocklist
add_filter( ‘frostycache_dangerous_routes’, function( $routes ) { $routes[] = ‘/myapp/v1/webhook’; return $routes; } );

frostycache_generate_cache_key

Filter

Customize the cache key. Default is an MD5 hash of the serialized request details.

Example: Include user role in cache key
add_filter( ‘frostycache_generate_cache_key’, function( $key, $data, $request ) { $user = wp_get_current_user(); if ( $user->ID ) { return md5( $data . implode( ‘,’, $user->roles ) ); } return $key; }, 10, 3 );

frostycache_cache_dir

Filter

Change the directory where cached JSON files are stored.

Example: Store cache on a separate disk
add_filter( ‘frostycache_cache_dir’, function() { return ‘/mnt/ssd/frostycache_cache/’; } );

frostycache_etag

Filter

Customize the ETag value used for conditional requests (HTTP 304).

Example: Use SHA-256 instead of MD5
add_filter( ‘frostycache_etag’, function( $etag, $result ) { return ‘”‘ . hash( ‘sha256’, wp_json_encode( $result ) ) . ‘”‘; }, 10, 2 );

frostycache_cache_data

Filter

Modify the complete cache data structure (data, headers, ETag, expiry timestamp) before saving to disk.

Example: Add a timestamp to cached data
add_filter( ‘frostycache_cache_data’, function( $data ) { $data[‘cached_at’] = time(); return $data; } );

frostycache_cache_headers

Filter

Modify all response headers before they are cached.

Example: Add a custom header to cached responses
add_filter( ‘frostycache_cache_headers’, function( $headers ) { $headers[‘X-Powered-By’] = ‘FrostyCache’; return $headers; } );

frostycache_cache_header

Filter

Modify an individual response header value before caching.

Example: Override Cache-Control for all cached responses
add_filter( ‘frostycache_cache_header’, function( $value, $key ) { if ( $key === ‘Cache-Control’ ) { return ‘public, max-age=3600, s-maxage=86400’; } return $value; }, 10, 2 );

frostycache_load_headers

Filter

Add extra headers when serving a cached response.

Example: Add CORS headers to cached responses
add_filter( ‘frostycache_load_headers’, function( $headers ) { $headers[‘Access-Control-Allow-Origin’] = ‘*’; return $headers; } );

frostycache_304_response

Filter

Filter the 304 Not Modified response before sending it to the client.

Example: Add a tracking header to 304 responses
add_filter( ‘frostycache_304_response’, function( $response ) { $response->header( ‘X-304-Served’, ‘true’ ); return $response; } );

frostycache_cache_request_details

Filter

Add custom properties to the cached request details (used in cache key generation).

Example: Vary cache by a custom header
add_filter( ‘frostycache_cache_request_details’, function( $args, $request ) { $args[‘currency’] = $request->get_header( ‘X-Currency’ ); return $args; }, 10, 2 );

frostycache_associate_list_items

Filter

Control whether items in list endpoint responses are associated with the cache key for targeted invalidation.

Example: Disable item association for a custom endpoint
add_filter( ‘frostycache_associate_list_items’, function( $associate, $result, $request ) { if ( str_contains( $request->get_route(), ‘/myapp/v1/feed’ ) ) { return false; } return $associate; }, 10, 3 );

Actions

frostycache_before_cache_save

Action

Fires before a cache file is written to disk. Use for logging or validation.

Example: Log cache writes
add_action( ‘frostycache_before_cache_save’, function( $file, $data, $key ) { error_log( ‘FrostyCache: caching ‘ . $key . ‘ to ‘ . $file ); }, 10, 3 );

frostycache_after_cache_save

Action

Fires after a cache file is successfully written to disk.

Example: Purge CDN after cache write
add_action( ‘frostycache_after_cache_save’, function( $file, $data, $key ) { my_cdn_purge( $key ); }, 10, 3 );

frostycache_save_cache_key

Action

Allows custom REST endpoints to save their cache keys for targeted invalidation.

Example: Track cache keys in a custom table
add_action( ‘frostycache_save_cache_key’, function( $request, $uri, $key ) { my_save_cache_key_mapping( $uri, $key ); }, 10, 3 );

frostycache_before_cache_delete

Action

Fires before cache files are deleted (both full clear and targeted delete).

Example: Log cache purges
add_action( ‘frostycache_before_cache_delete’, function( $keys, $post_id ) { error_log( ‘FrostyCache: purging ‘ . count( $keys ) . ‘ files for post ‘ . $post_id ); }, 10, 2 );

frostycache_cache_cleared

Action

Fires after the entire cache has been cleared. No parameters.

Example: Notify after full cache flush
add_action( ‘frostycache_cache_cleared’, function() { do_action( ‘my_slack_notify’, ‘FrostyCache cache was flushed’ ); } );

frostycache_after_cache_delete

Action

Fires after cache files have been deleted for a specific post.

Example: Warm cache after invalidation
add_action( ‘frostycache_after_cache_delete’, function( $post_id ) { wp_remote_get( rest_url( ‘wp/v2/posts/’ . $post_id ) ); } );

WP-CLI Commands

wp frostycache flush

Clear the entire FrostyCache cache. All cached JSON files are deleted.

wp frostycache clear-post <id>

Clear cache files associated with a specific post ID and all related endpoints.

<id> (required) — The post ID to clear

wp frostycache clear-route <route> [–query=<query>]

Clear the cached response for one exact route — useful for custom REST endpoints with no post-type/meta tracking, or stale caches written before a frostycache_skip_cache rule existed. Works even if the route never registered a cache key association.

<route> (required) — The REST route as in WP_REST_Request::get_route(), e.g. /cocart/v2/checkout (no /wp-json prefix, no query string)
[--query=<query>] (optional) — The query string exactly as sent with the request, e.g. "category=22". Omit for routes requested with no query parameters

wp frostycache clear-index <type>

Clear index/list caches for a custom endpoint type that is not tied to a post type — caches saved via frostycache_index_cache_keys_{type} options, e.g. custom routes hooked into frostycache_save_cache_key.

<type> (required) — The index type, i.e. the suffix in the frostycache_index_cache_keys_{type} option name (e.g. wc_products, taxonomies)

wp frostycache status

Show cache statistics: file count, total size, and cache directory path.

wp frostycache cleanup

Remove expired cache files. Runs automatically via WP-Cron (twicedaily).

wp frostycache warm [–post_type=<type>] [–limit=<number>] [–per-page=<number>] [–delay=<ms>] [–dry-run]

Pre-populate the cache for published posts and pages by issuing real loopback HTTP requests to their REST API endpoints — the same request path a real visitor would trigger, sent unauthenticated with no cookies so the cache is actually written. Reports a progress bar while running and a summary of successes/failures when done.

[--post_type=<type>] (optional) — Comma-separated list of post types to warm. Default: post,page
[--limit=<number>] (optional) — Maximum number of items to warm. Default: all matching items
[--per-page=<number>] (optional) — Number of posts to query per batch. Default: 100
[--delay=<ms>] (optional) — Milliseconds to sleep between requests. Default: 0
[--dry-run] (optional) — List the URLs that would be warmed without making any requests

wp frostycache repair [–force]

Repair the cache layer: reinstalls the MU plugin fallback and the advanced-cache.php drop-in. If another cache plugin owns the drop-in it is left in place (REST API caching stays active via the MU plugin) unless --force is passed. Prints the cache layer status when done.

[--force] (optional) — Overwrite advanced-cache.php even if owned by another plugin

wp frostycache license <action> [<key>]

Manage the plugin license. Actions: activate, deactivate, status.

<action> (required) — activate, deactivate, or status
[<key>] (optional) — License key (required for activate)

wp frostycache rollback [–version=<version>]

Rollback to a previous plugin version. Requires a valid license. Omit --version to list available versions.