Caching WordPress REST API responses can speed up your site, reduce server load, and improve scalability. Here’s how you can do it:
- Use Plugins: Install plugins like W3 Total Cache Pro (built-in REST API support) or WP Rocket (requires an additional helper plugin).
- Server-Side Caching: Configure tools like Nginx, Redis, or Memcached for more control over caching.
- Set Cache Durations: Adjust cache expiration times based on content type (e.g., static pages: 24 hours, user data: 15 minutes).
- Exclude Dynamic Endpoints: Skip caching for routes with real-time or user-specific data.
- Test and Verify: Use browser tools, Postman, or cURL to ensure caching is working as expected.
Quick Comparison of Plugins and Tools:
| Tool/Plugin | Features | REST API Support |
|---|---|---|
| W3 Total Cache Pro | Server-side caching, route exclusions | Built-in support |
| WP Rocket | Page and browser caching | Needs helper plugin |
| Nginx | FastCGI caching for REST API | Manual configuration |
| Redis | Object caching with persistence | Requires setup |
| Memcached | High memory efficiency | Basic data caching |
Caching improves performance but requires careful setup to avoid stale data or conflicts. Follow these steps to optimize your WordPress REST API responses effectively.
How to Enable Redis Cache for WordPress
WordPress Caching Plugins Setup
If you’re dealing with caching challenges, using specialized plugins can help optimize your REST API responses.
Top Caching Plugins
For caching WordPress REST API responses, two plugins are often recommended:
| Plugin | Features | REST API Support |
|---|---|---|
| W3 Total Cache Pro | – Server-side caching – Last Modified time–based cache – Route exclusion options | Built-in support |
| WP Rocket | – Page caching – Browser caching | Requires helper plugin |
Testing shows that W3 Total Cache Pro can reduce response times by 84.5% (from 968 ms to 150 ms) and lower server load by 40% (from 0.62 to 0.37) [1]. While WP Rocket delivers excellent page caching, it needs an additional plugin for REST API caching.
Plugin Setup Steps
Here’s how to set up REST API caching with W3 Total Cache Pro:
- Install and activate W3 Total Cache Pro.
- Go to Performance → General Settings.
- Enable Page Cache in the General section and save your settings.
- Navigate to Performance → Page Cache.
- Find and enable the REST API caching option.
- Save your Page Cache settings.
After this, you can adjust your REST API caching settings for better performance.
REST API Cache Settings
Here’s how to configure key REST API caching parameters:
- Cache Duration Settings
Set cache expiration times based on how often your content updates. Configure cache purge rules to align with these updates and enable automatic cache clearing when content changes. - Route Exclusion Configuration
Use regular expressions to exclude specific REST routes that generate dynamic data. This is especially important for endpoints handling user-specific or real-time information.
"Settings for your REST API Cache will follow the same rules as other types of page caching, and are purged based on the Last Modified time of the query, and when you manually purge your caches." [1]
- Performance Verification
After setup, use your browser’s developer tools to check for reduced response times, correct cache headers, and expected caching behavior across your endpoints.
Research from BoldGrid highlights that caching static REST responses can dramatically improve response times and reduce server load [1].
Server-Side Cache Setup
Here’s how to set up server-side caching to improve WordPress REST API performance by cutting down on database queries and reducing PHP processing load.
Nginx Cache Configuration
Nginx’s FastCGI Cache is a great way to cache REST API responses. Below is an example configuration for setting up a FastCGI cache zone and applying caching rules specifically for the /wp-json/ endpoint:
# Define FastCGI Cache Zone fastcgi_cache_path /tmp/nginx-cache levels=1:2 keys_zone=wordpress:100m inactive=60m; # REST API Cache Configuration location /wp-json/ { fastcgi_cache wordpress; fastcgi_cache_key "$request_method$request_uri$http_authorization"; fastcgi_cache_valid 200 60m; fastcgi_cache_use_stale error timeout http_500 http_503; fastcgi_cache_bypass $http_pragma; fastcgi_cache_methods GET HEAD; include fastcgi_params; fastcgi_pass php-fpm; } This setup speeds up REST API responses by caching them effectively, reducing the load on the database and PHP processor.
Redis and Memcached Setup
Object caching solutions like Redis and Memcached can further enhance performance. Both have their advantages:
| Feature | Redis | Memcached |
|---|---|---|
| Data Persistence | Yes | No |
| Memory Efficiency | Moderate | High |
| Complex Data Types | Supported | Basic only |
| Scalability | Master-slave setup | Distributed system |
Setting up Redis caching:
- Install the Redis server and the PHP Redis extension.
- Add these lines to your
wp-config.phpfile:define('WP_CACHE', true); define('WP_REDIS_HOST', '127.0.0.1'); define('WP_REDIS_PORT', 6379); define('WP_REDIS_TIMEOUT', 1); define('WP_REDIS_READ_TIMEOUT', 1); define('WP_REDIS_DATABASE', 0);
Redis provides a powerful caching layer, especially useful when handling large datasets or complex operations.
PHP Opcache Setup
Using PHP Opcache reduces script compilation overhead, making REST API calls faster. Here’s a recommended configuration for WordPress, particularly for PHP 8.0+:
opcache.memory_consumption=256 opcache.interned_strings_buffer=16 opcache.max_accelerated_files=100000 opcache.revalidate_freq=0 opcache.fast_shutdown=1 opcache.enable_cli=1 opcache.jit=1235 opcache.jit_buffer_size=100M This configuration optimizes PHP performance and ensures smoother API responses, especially in high-traffic environments.
sbb-itb-77ae9a4
Cache Management
Managing cache for WordPress REST API responses involves setting appropriate durations, defining exclusions, and creating rules for user-specific data to ensure fast performance without compromising accuracy.
Cache Duration Settings
Setting the right cache duration is key to balancing speed and content freshness. Here’s a suggested framework based on the type of content:
| Content Type | Cache Duration | Update Frequency |
|---|---|---|
| Static Pages | 24 hours | Low |
| Blog Posts | 6 hours | Medium |
| Product Data | 1 hour | High |
| User Data | 15 minutes | Very High |
| Real-time Data | No cache | Immediate |
You can adjust cache durations programmatically using WordPress filters. For example, to set a 6-hour cache for posts:
add_filter('rest_cache_duration', function($duration, $request) { if (strpos($request->get_route(), '/wp/v2/posts') !== false) { return 21600; // 6 hours in seconds } return $duration; }, 10, 2); No-Cache Endpoints
Some endpoints handle dynamic or sensitive data that shouldn’t be cached. These can be excluded using filters:
add_filter('rest_cache_skip_endpoints', function($endpoints) { return array( '/wp/v2/users/me', '/wc/v3/orders/*', '/wp/v2/comments', '/custom/real-time-data' ); }); For Nginx users, you can bypass caching for specific endpoints by adding location blocks:
location ~ ^/wp-json/wp/v2/users/me { fastcgi_cache_bypass 1; fastcgi_no_cache 1; } User-Specific Cache Rules
When dealing with personalized data, caching needs to account for user roles and logged-in statuses. You can modify cache keys to reflect user-specific variations:
add_filter('rest_cache_key', function($key, $request) { if (is_user_logged_in()) { $user = wp_get_current_user(); $key .= '_role_' . implode('-', $user->roles); } return $key; }, 10, 2); For endpoints that require fully personalized responses, you can segment cache strategies as follows:
| User Type | Strategy | Implementation Method |
|---|---|---|
| Anonymous | Shared cache | Standard cache key |
| Logged-in | Per-user cache | User ID in cache key |
| Admin | No cache | Cache bypass |
Additionally, you can configure cache variations based on authentication cookies:
add_filter('rest_cache_headers', function($headers) { $headers['Vary'] = 'Cookie, Authorization'; return $headers; }); Testing and Fixes
Cache Testing Tools
Once caching is set up, it’s important to check how well it’s working. Here are some tools and methods you can use:
- Browser Developer Tools
Open Chrome DevTools (press F12), go to the Network tab, and look at API responses for caching headers likex-wp-cache,Cache-Control, andExpires. - Postman
Send a GET request to your API, review the cache headers, then resend the request to see if the response time improves. - cURL Command-Line Testing
Use the following cURL command to check caching headers:curl -I -X GET https://your-site.com/wp-json/wp/v2/posts \ -H "Accept: application/json" \ -H "Content-Type: application/json"
Common Cache Problems
Here are some frequent caching issues and how to address them:
| Issue | Cause | Solution |
|---|---|---|
| Stale Data | Cache invalidation not working | Set up proper cache purging when content is updated. |
| Plugin Conflicts | Security and caching plugin issues | Check compatibility and adjust caching plugin settings as needed. |
If you’re using security plugins like Wordfence or iThemes Security and they conflict with caching, you can add the following to your wp-config.php file:
define('DONOTCACHEPAGE', false); define('DONOTCACHEOBJECT', false); define('DONOTCACHEDB', false); Cache Clearing Guide
Automated Cache Clearing
You can use the following snippet to automatically clear the cache when a post is updated:
add_action('save_post', function($post_id) { if (defined('DOING_AUTOSAVE') && DOING_AUTOSAVE) return; wp_cache_delete('rest-api-post-' . $post_id, 'rest-cache'); do_action('rest_cache_purge_post', $post_id); }); Manual Cache Clearing
Manually clear your cache in these scenarios:
- After major plugin updates
- When adding new API endpoints
- After making large content changes
- While troubleshooting cache-related issues
For server-level cache clearing, use the following commands:
# Nginx FastCGI Cache rm -rf /var/run/nginx-cache/* # Redis redis-cli FLUSHALL # Memcached echo 'flush_all' | nc localhost 11211 Next Steps
Overview
Let’s break down the essential steps for improving REST API caching in WordPress. Effective caching requires careful planning and ongoing adjustments to ensure optimal performance.
- Use WordPress caching plugins for an easy setup.
- Leverage server-side tools like Nginx, Redis, and Memcached for more control and flexibility.
When managing your cache, consider these key points:
- Adjust cache durations and exclusions based on how sensitive the content is.
- Tailor caching settings for user-specific data to maintain personalized experiences.
For more detailed guidance, check out the resources below.
WP Winners Resources
WP Winners offers a variety of tools to help you fine-tune your REST API caching. Here’s a quick look at what they provide:
| Resource Type | Description | Benefits |
|---|---|---|
| Performance Monitoring Guide | Learn how to track API response times effectively. | Spot performance issues and tweak settings. |
| Cache Configuration Templates | Ready-to-use settings for popular caching tools. | Simplify setup and follow best practices. |
| Troubleshooting Handbook | Solutions for common caching problems. | Resolve issues quickly and efficiently. |
For more advanced tips and tutorials, WP Winners also provides in-depth resources to help you implement caching strategies. Want to stay ahead with the latest WordPress caching techniques? Subscribe to their newsletter for updates and expert advice.
Related posts
- WordPress REST API Errors: Debugging Guide
- WordPress REST API: Automate Tasks in 2024
- WordPress Object Cache: Boost Site Speed in 2024
- 10 Tips to Optimize WordPress REST API Caching
Adding HTTP cache headers to REST responses
WordPress sends no-cache on most REST responses, so browsers, proxies and CDNs revalidate every request. For read-heavy public endpoints you can attach proper cache headers and let edge layers serve repeat requests without hitting PHP. The rest_pre_serve_request filter fires after the response is built but before headers are flushed, which is the right place to set them.
add_filter( 'rest_pre_serve_request', 'osom_rest_cache_headers', 10, 4 );
function osom_rest_cache_headers( $served, $result, $request, $server ) {
// Only cache safe, read-only requests.
if ( 'GET' !== $request->get_method() ) {
return $served;
}
$route = $request->get_route();
// Never cache authenticated, settings or user routes.
if ( is_user_logged_in()
|| preg_match( '#^/wp/v2/(users|settings)#', $route ) ) {
nocache_headers();
return $served;
}
// Public content: cache at the edge for 5 min, browser for 1 min.
header( 'Cache-Control: public, max-age=60, s-maxage=300' );
return $served;
}
ETag and Last-Modified for revalidation
Validators let a client send If-None-Match or If-Modified-Since and receive a cheap 304 Not Modified when nothing changed. rest_post_dispatch gives you the dispatched WP_REST_Response, so you can derive an ETag from the body and short-circuit with a 304.
add_filter( 'rest_post_dispatch', 'osom_rest_etag', 10, 3 );
function osom_rest_etag( $response, $server, $request ) {
if ( 'GET' !== $request->get_method() || $response->is_error() ) {
return $response;
}
$etag = '"' . md5( wp_json_encode( $response->get_data() ) ) . '"';
$response->header( 'ETag', $etag );
$client_etag = $request->get_header( 'if_none_match' );
if ( $client_etag && trim( $client_etag ) === $etag ) {
$response->set_status( 304 );
$response->set_data( null );
}
return $response;
}
Excluding specific routes from cache
Some endpoints must always be fresh — carts, nonces, anything user-specific. Maintain a small list of route patterns and force no-store when the current route matches, before any cache headers are applied.
function osom_route_is_uncacheable( $route ) {
$never_cache = array(
'#^/wp/v2/users#',
'#^/wc/store/cart#',
'#^/[^/]+/v\d+/.*nonce#',
);
foreach ( $never_cache as $pattern ) {
if ( preg_match( $pattern, $route ) ) {
return true;
}
}
return false;
}
Call osom_route_is_uncacheable( $request->get_route() ) inside the header filter above and return early with header( 'Cache-Control: no-store, max-age=0' ) when it returns true.
Cache-aside with transients for expensive endpoints
HTTP caching only helps after the first hit. For a custom endpoint that runs slow queries or external API calls, wrap the work in the cache-aside pattern: look in a transient first, compute and store on a miss. With a persistent object cache (Redis/Memcached) the transient lives in memory.
register_rest_route( 'osom/v1', '/report', array(
'methods' => 'GET',
'permission_callback' => '__return_true',
'callback' => 'osom_get_report',
) );
function osom_get_report( WP_REST_Request $request ) {
$key = 'osom_report_' . md5( $request->get_param( 'range' ) );
$data = get_transient( $key );
if ( false === $data ) {
$data = osom_build_expensive_report( $request ); // slow query / API call
set_transient( $key, $data, 10 * MINUTE_IN_SECONDS );
}
return rest_ensure_response( $data );
}
Invalidate the transient on the relevant save_post or woocommerce_* hook with delete_transient() so editors never see stale data.
CDN and edge considerations
- Use
s-maxagefor shared caches. A CDN respectss-maxageovermax-age, so you can cache hard at the edge while keeping browser caching short. - Add
Varywhen responses differ by request. If output changes withAccept-Languageor auth, send a matchingVaryheader to prevent the edge serving the wrong variant. - Strip cookies on cacheable REST routes. Many CDNs bypass cache when a
Set-Cookieis present; ensure public GET routes do not start sessions. - Purge on write. Pair transient invalidation with a CDN purge (most CDNs offer a purge-by-URL API) so edge and origin expire together.
- Surrogate-Control for Varnish/Fastly.
Surrogate-Control: max-age=86400lets the edge cache for a day whileCache-Control: max-age=60keeps browsers honest.




