WordPress Custom Fields Cache — Redis & Memcached | Field Forge
Download Log in

Object Cache + Query Batching — Enterprise Performance

Field Forge integrates with WordPress’s object cache API (wp_cache_*) for fast field value lookups, plus provides a batch_load() API for eliminating N+1 query problems on large sites. Combined with custom table storage, this makes Field Forge the fastest WordPress custom fields plugin on high-traffic sites.


WordPress object cache basics

WordPress’s wp_cache_* functions provide a caching layer that sits between your code and the database. By default, WordPress uses a per-request in-memory cache (cleared at the end of each request). With a persistent object cache backend like Redis or Memcached, the cache survives between requests — subsequent pageviews hit the cache instead of the database.

On a high-traffic site with Redis:

  • First pageview: fetches from database, stores in Redis
  • Second pageview (same data): hits Redis, skips database entirely
  • Third pageview: hits Redis

For read-heavy workloads, this is a 10–100x performance improvement.

Field Forge and object cache

Every field value read in Field Forge goes through the object cache:

// Inside Field Forge's get_field() implementation (simplified)
$cached = wp_cache_get($cache_key, 'fieldforge');
if ($cached !== false) {
    return $cached;
}

$value = $this->fetch_from_database($post_id, $field_name);
wp_cache_set($cache_key, $value, 'fieldforge', 3600);
return $value;
  • Cache key formatfieldforge:{post_id}:{field_name}
  • Cache groupfieldforge (separate from other plugins)
  • Expiration — 1 hour default, configurable via filter
  • Cache miss handling — falls through to database query, then caches result

Cache invalidation

When a field value is updated or deleted, Field Forge automatically invalidates the relevant cache entries:

// Inside update_field() (simplified)
$this->save_to_database($post_id, $field_name, $value);
wp_cache_delete("fieldforge:{$post_id}:{$field_name}", 'fieldforge');

Invalidation is:

  • Immediate — on save, the old cache entry is deleted
  • Precise — only the specific field’s cache is invalidated, not the whole post’s
  • Hooked — plugins can add custom invalidation logic via fieldforge/cache/invalidate hook

Supported cache backends

Field Forge works with any WordPress object cache backend:

Redis

Most common for managed WordPress hosting. Free plugins: “Redis Object Cache” or “W3 Total Cache” with Redis enabled. Provides persistent caching across requests.

Memcached

Older but still supported. Plugins: “Memcached” or “W3 Total Cache.”

APCu

Single-server caching that’s faster than Redis/Memcached for lower-traffic sites (no network hop). Plugins: “APCu Object Cache.”

Default in-memory cache

If no persistent object cache backend is installed, Field Forge falls back to WordPress’s default in-request cache. Caching still happens within a single pageview, but not between requests. Works everywhere, zero configuration.

Batch loading

For archive pages and list views where you’re rendering many posts at once, Field Forge provides a batch_load() API that fetches custom fields for multiple posts in a single SQL query:

$post_ids = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
FieldForge::batch_load($post_ids);

// All subsequent get_field() calls on these post IDs hit the cache
foreach ($post_ids as $id) {
    $hero_title = get_field('hero_title', $id);  // Cache hit
    $hero_image = get_field('hero_image', $id);  // Cache hit
}

Without batch_load(), the above would fire 20 separate SQL queries (10 posts × 2 fields each). With batch loading, it’s 1 query.

Automatic preloading

Field Forge hooks into WordPress’s the_posts filter to run batch loading automatically on any query that returns multiple posts:

// Field Forge's internal hook
add_filter('the_posts', function($posts) {
    if (!empty($posts)) {
        $post_ids = wp_list_pluck($posts, 'ID');
        FieldForge::batch_load($post_ids);
    }
    return $posts;
});

Archive pages, search results, category listings, and REST API list endpoints all benefit automatically. No code changes needed in your theme.

Explicit batch loading for custom queries

For WP_Query calls in custom templates, you can explicitly batch-load after the query:

$query = new WP_Query([
    'post_type' => 'product',
    'posts_per_page' => 30,
    'category_name' => 'featured',
]);

// Batch load custom fields for all 30 products in one query
if ($query->have_posts()) {
    $post_ids = wp_list_pluck($query->posts, 'ID');
    FieldForge::batch_load($post_ids);
}

// Now rendering the loop is cache-hit only
while ($query->have_posts()) : $query->the_post();
    $price = get_field('price');        // Cache hit
    $sku = get_field('sku');            // Cache hit
    $features = get_field('features');  // Cache hit
endwhile;

Performance comparison

On a test site with 10,000 posts, 15 custom fields per post:

Without object cache

Action Time
Single post pageview 45ms custom field queries
Archive (20 posts) 840ms custom field queries (N+1)
WooCommerce category (30 products) 1,260ms

With Redis object cache (warm cache)

Action Time
Single post pageview 3ms (cache hits)
Archive (20 posts) 12ms (cache hits)
WooCommerce category (30 products) 18ms

With Redis object cache + batch_load on cold cache

Action Time
Single post pageview 12ms (1 query + cache populate)
Archive (20 posts) 95ms (1 batch query + cache populate)
WooCommerce category (30 products) 142ms (1 batch query + cache populate)

The combination of object cache and batch loading is dramatic on high-traffic sites.

Monitoring cache performance

Field Forge provides WP-CLI commands for monitoring cache performance:

# Show cache stats
wp fieldforge cache stats

# Output:
# Cache hits:    94.3%
# Cache misses:  5.7%
# Avg hit time:  0.2ms
# Avg miss time: 8ms

For sites where cache hit rate is low (below 80%), investigate:

  • Is the persistent cache backend actually running?
  • Is cache invalidation too aggressive (clearing on every save)?
  • Are post types / field groups configured correctly?

Filter customization

Change cache expiration

add_filter('fieldforge/cache/expiration', function($seconds) {
    return DAY_IN_SECONDS;  // Cache for 24 hours
});

Disable caching for specific field groups

add_filter('fieldforge/cache/should_cache', function($should_cache, $field_group) {
    if ($field_group === 'frequently-changing-group') {
        return false;
    }
    return $should_cache;
}, 10, 2);

Custom invalidation logic

add_action('fieldforge/cache/invalidate', function($post_id, $field_name) {
    // Also invalidate related data
    wp_cache_delete("my_custom_cache:{$post_id}", 'my_plugin');
}, 10, 2);

Ready for enterprise-grade custom fields performance?

Get Field Forge — from $35/year →

Object cache integration and batch loading are in every version of Field Forge, including the free one.

Forge AI Assistant Online

Hi! I'm the Field Forge AI assistant. Ask me anything about the plugin — setup, features, troubleshooting, or development.

Just now
Powered by Forge AI · Browse docs