---
title: "Documentation — FrostyCache"
description: "FrostyCache developer documentation. Hooks, filters, WP-CLI commands, constants, and configuration reference for WordPress REST API caching."
language: "en-GB"
canonical_url: "https://frostycache.com/docs/"
source_url: "https://frostycache.com/docs/"
content_type: "text/markdown"
---

Documentation
  Developer Reference


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





| Section | Reference |
| --- | --- |
| [Overview](#overview) | How FrostyCache works, cache storage, skip parameter |
| [Constants](#constants) | `FROSTYCACHE_AGE`, `FROSTYCACHE_REST_PREFIX`, `FROSTYCACHE_FOLDER` |
| [Filters](#filters) | 14 filters for cache duration, skip logic, keys, headers, ETags, and more |
| [Actions](#actions) | 6 actions for cache save, delete, and clear lifecycle events |
| [WP-CLI](#cli) | `flush`, `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`](#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 endpointsadd_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 namespaceadd_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 noncesadd_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 blocklistadd_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 keyadd_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 diskadd_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 MD5add_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 dataadd_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 responsesadd_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 responsesadd_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 responsesadd_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 responsesadd_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 headeradd_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 endpointadd_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 writesadd_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 writeadd_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 tableadd_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 purgesadd_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 flushadd_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 invalidationadd_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.
