WordPress Caching Explained: Object Cache vs Transients vs Reality
Table of Contents
Ask five developers how WordPress caching works, and you’ll likely get five different answers.
The confusion usually centers around two systems:
- Object Cache
- Transients API
They look similar. They are often used interchangeably. But they behave very differently—especially when persistent caching (Redis, Memcached) enters the picture.
This article breaks down the real mechanics behind these systems so you can stop guessing and start designing efficient caching strategies.
The Big Picture
WordPress caching operates in layers:
Request
↓
Object Cache (in-memory)
↓
Persistent Cache (Redis/Memcached) [optional]
↓
Database (fallback)Transients sit on top of this system—but don’t behave the way most developers assume.
What is the Object Cache?
The Object Cache is a low-level caching system built into WordPress.
It stores data in memory during a request.
Basic Usage
<?php
\wp_cache_set( 'my_key', 'Hello World', 'my_group');
$value = \wp_cache_get( 'my_key', 'my_group');
echo $value;Key Characteristics
- In-memory (per request by default)
- Fast (no database hit)
- Grouped storage
- Not persistent unless extended
Persistent vs Non-Persistent Object Cache
Non-Persistent (Default)
Without any plugin:
- Cache exists only during the request
- Cleared at the end of execution
Persistent (Redis / Memcached)
With a drop-in like object-cache.php:
- Cache survives between requests
- Stored in Redis or Memcached
- Shared across processes
Example Behavior
// Request 1
\wp_cache_set( 'key', 'value' );
// Request 2
\wp_cache_get( 'key' ); // NULL without persistent cacheWith Redis:
// Request 2
\wp_cache_get( 'key' ); // 'value'Cache Groups (Underrated Feature)
Every cache entry belongs to a group.
<?php
\wp_cache_set( 'user_1', $data, 'users' );
\wp_cache_set( 'post_1', $data, 'posts' );This allows:
- Logical separation
- Selective invalidation
- Performance tuning
Persistent Groups
Some groups are always persistent:
<?php
\wp_cache_add_global_groups( ['users', 'site-options'] );These are shared across requests even in multisite setups.
What Are Transients?
Transients are a higher-level caching API.
They provide:
- Expiration support
- Simplified interface
Basic Usage
<?php
\set_transient( 'my_data', 'Hello World', 3600 );
$value = \get_transient( 'my_data' );Where Are Transients Stored?
This is where confusion begins.
- Without persistent cache → stored in database
- With persistent cache → stored in object cache
Transients Internals
Without Redis/Memcached:
wp_options table:
_transient_my_data
_transient_timeout_my_dataWith Redis:
They bypass the database entirely.
Critical Misconception #1
“Transients are always database-based.”
False.
They are only database-backed when no persistent object cache exists.
Critical Misconception #2
“Transients always expire exactly on time.”
False.
Expiration is a maximum lifetime, not a guarantee.
They can disappear earlier due to:
- Cache eviction (Redis/Memcached)
- Manual deletion
- Database cleanup
Critical Misconception #3
“Object cache and transients are separate systems.”
Not really.
Transients often use the object cache under the hood.
Redis / Memcached Behavior
With persistent caching:
- Object cache becomes global
- Transients skip database
- Cache eviction policies apply
Example: Eviction Risk
If Redis memory is full:
- Least recently used keys are removed
- Transients may disappear early
Real-World Example: API Caching
<?php
$data = \get_transient( 'api_response' );
if ( $data === false ) {
$data = file_get_contents( 'https://api.example.com/data' );
\set_transient( 'api_response', $data, 600 );
}
echo $data;This works across both database and Redis setups.
Advanced Pattern: Hybrid Caching
<?php
$key = 'expensive_query';
$data = \wp_cache_get( $key, 'custom' );
if ( $data === false ) {
$data = \get_transient( $key );
if ( $data === false ) {
$data = run_expensive_query();
\set_transient( $key, $data, 3600 );
}
\wp_cache_set( $key, $data, 'custom' );
}This combines:
- Fast in-memory cache
- Persistent fallback
Performance Implications
- Object cache reduces repeated computation
- Persistent cache eliminates database hits
- Transients simplify expiration logic
But misuse leads to:
- Cache bloat
- Stale data
- Unpredictable expiration
When to Use What
Use Object Cache When:
- Within a single request
- You need maximum speed
- No expiration needed
Use Transients When:
- You need expiration
- Data should persist across requests
- Simplicity matters
Key Insight Most Developers Miss
Transients are not a storage system—they are a caching hint.
Object cache is not persistent—unless you make it so.
Once you understand this, everything becomes predictable.
FAQ
What is the difference between object cache and transients?
Object cache is a low-level in-memory caching system, while transients are a higher-level API that adds expiration and may use the object cache internally.
Are transients stored in the database?
Only when no persistent object cache is available. Otherwise, they are stored in memory systems like Redis.
Do transients expire exactly on time?
No, expiration is a maximum lifetime and transients can be removed earlier.
What is a persistent object cache?
It is an external caching system like Redis or Memcached that allows cache data to persist across requests.
Should I use Redis or Memcached?
Both are excellent, but Redis is more commonly used in modern WordPress setups due to flexibility and features.
Can I rely on transients for critical data?
No, transients should only be used for cacheable data since they can disappear at any time.
Final takeaway: WordPress caching isn’t confusing once you realize one thing—everything depends on whether your cache persists or not.