Skip to main content

Drupal Core Performance: When Caching Is Slower Than Just Doing the Work

· 5 min read
Victor Jimenez
Software Engineer & AI Agent Builder

Caching is usually the answer to everything in Drupal performance, but there is a crossover point where the overhead of the cache itself -- retrieval and unserialization -- outweighs the cost of just doing the work.

TL;DR — 30 second version
  • JSON:API normalization caching can be slower than raw normalization for simple entities
  • If (Fetch + Unserialize) > Normalize, the cache is a net loss
  • Core is proposing to skip caching when normalization is "trivial"
  • OptimizedPhpArrayDumper is also getting performance work for faster cold boots

Why I Dug In

Performance tuning often relies on "rules of thumb" (e.g., "cache everything"), but high-scale sites live or die by the exceptions to these rules. I wanted to understand exactly when the cost of unserialize() exceeds the cost of normalize() in JSON:API, and how core developers are shaving cycles off the OptimizedPhpArrayDumper.

The Paradox of Caching

Issue #3572098 highlights a fascinating edge case. For simple entities or sparse fieldsets, the normalization process (converting an entity to an array) is incredibly fast. However, the JSON:API normalization cache mechanism adds overhead:

  1. Generation: Normalization happens anyway.
  2. Storage: The result is serialized and written to the cache backend (Database, Redis, Memcached).
  3. Retrieval: The next request fetches the string.
  4. Unserialization: PHP parses the string back into an array.

If (Fetch + Unserialize) > Normalize, the cache is a net loss.

The Solution: Intelligent Caching

The proposal in core is to skip caching when the normalization is "trivial" or when the overhead is proven to be higher. This is similar to how the Internal Page Cache has exclusion rules, but applied at a much more granular level.

On a related note, issue #3571858 is tackling the OptimizedPhpArrayDumper. This class is responsible for dumping the compiled service container to a PHP array. It is a critical path operation during a "cold cache" boot. Any optimization here pays dividends every time you deploy or clear caches.

Benchmarking the Crossover

Benchmark: normalize vs cache retrieval
$start = microtime(true);
$serializer->normalize($entity, 'api_json');
$normalization_time = microtime(true) - $start;

$start = microtime(true);
$cache = $backend->get($cid);
unserialize($cache->data);
$cache_time = microtime(true) - $start;

if ($cache_time > $normalization_time) {
print "Caching is SLOWER for this entity type.\n";
}
OptimizedPhpArrayDumper context
// In OptimizedPhpArrayDumper.php
// Avoiding function calls or complex logic in tight loops
// can shave milliseconds off container generation.
// (See issue #3571858 for the actual patch)
Top Takeaway

"Cache it" is not always the right move. For lightweight data structures, PHP's execution speed often beats the I/O roundtrip of a cache. Trust benchmarks, not rules of thumb.

Context

Container compilation performance affects developer velocity and downtime windows. While we focus on runtime performance, deployment performance (container compilation) is where the OptimizedPhpArrayDumper work pays off.

The Code

I am starting a project to benchmark these specific scenarios -- comparing raw normalization vs. cache retrieval across different entity complexities and cache backends.

View Code

What I Learned

  • Trust, but verify benchmarks: "Cache it" is not always the right move. For lightweight data structures, PHP's execution speed often beats the I/O roundtrip of a cache.
  • Serialization is not free: unserialize() can be CPU intensive, especially for deep arrays.
  • Container compilation matters: While we focus on runtime performance, deployment performance (container compilation) affects developer velocity and downtime windows.
  • Drupal Core is getting sharper: It is encouraging to see core developers revisiting these foundational assumptions 10+ years into the project.

Signal Summary

TopicSignalActionPriority
JSON:API Cache OverheadCache can be slower than normalizeBenchmark your entity typesHigh
unserialize() CostCPU intensive for deep arraysProfile serialization pathsMedium
OptimizedPhpArrayDumperCold boot optimizationWatch issue #3571858Medium
Intelligent CachingSkip cache for trivial normalizationsAdopt when patch landsHigh

Why This Matters for Drupal and WordPress

Drupal sites serving decoupled frontends via JSON:API need to benchmark whether their entity normalization cache is actually helping or hurting — especially for simple content types with few fields. WordPress developers using the REST API face the same "cache everything" trap; the WP object cache and transients API can add overhead for lightweight responses. Both platforms benefit from profiling serialization costs before blindly enabling caching layers on API endpoints.

References


Looking for an Architect who doesn't just write code, but builds the AI systems that multiply your team's output? View my enterprise CMS case studies at victorjimenezdev.github.io or connect with me on LinkedIn.