Drupal Core Performance: When Caching Is Slower Than Just Doing the Work
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:
- Generation: Normalization happens anyway.
- Storage: The result is serialized and written to the cache backend (Database, Redis, Memcached).
- Retrieval: The next request fetches the string.
- 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
$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";
}
// 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)
"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.
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.
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
| Topic | Signal | Action | Priority |
|---|---|---|---|
| JSON:API Cache Overhead | Cache can be slower than normalize | Benchmark your entity types | High |
| unserialize() Cost | CPU intensive for deep arrays | Profile serialization paths | Medium |
| OptimizedPhpArrayDumper | Cold boot optimization | Watch issue #3571858 | Medium |
| Intelligent Caching | Skip cache for trivial normalizations | Adopt when patch lands | High |
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
- JSON:API normalisation caching can be more expensive than normalisation
- Optimize OptimizedPhpArrayDumper further
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.
