Analyzing cache hit/miss ratiosfor Drupal 8 , 9 , 10 , and 11

Last updated :  

You've configured a backend and tuned its settings — but without measuring, you're guessing. A cache hit/miss ratio is the single most useful number for judging whether your caching setup is actually working: it tells you what fraction of cache lookups found something useful versus had to fall through to the expensive, uncached path.

What you'll learn in this lesson

  • What a hit/miss ratio actually measures, and why a "high" number isn't automatically good
  • How to read hit/miss statistics directly from Redis or Memcache
  • Why some cache bins are expected to have a naturally low hit rate — and that's fine

What the ratio actually tells you

A cache hit means \Drupal::cache()->get($cid) found a valid value and returned it immediately. A cache miss means it returned FALSE, and whatever called it had to do the real work — a database query, a render pipeline run, an external API call — before storing the result for next time. The hit/miss ratio is simply hits / (hits + misses) over some time window. A high ratio means most requests are being served from cache instead of doing expensive work; a low one means your cache isn't earning its keep, either because things expire too fast, get invalidated too aggressively, or the underlying data genuinely changes on nearly every request.

Reading stats from your cache backend directly

Both Redis and Memcache expose their own hit/miss counters independently of anything Drupal-specific — these are the most reliable numbers because they come straight from the backend itself, not from application-level instrumentation that could have gaps.

# Redis
redis-cli INFO stats | grep keyspace

# Memcache (via the memcached binary protocol stats command)
echo "stats" | nc 127.0.0.1 11211 | grep -E "get_hits|get_misses"

Redis's INFO stats output includes keyspace_hits and keyspace_misses counters; Memcache's stats command reports get_hits and get_misses directly. Both are cumulative since the process started, so to get a meaningful ratio for "right now" you need to sample them twice a known interval apart and compute the difference, rather than reading the raw cumulative numbers once.

A low hit rate on some bins is completely normal and not a problem to fix. A bin holding data that's genuinely unique per request — a per-user notification count, a one-time CSRF token — will always have a near-zero hit rate no matter how well-tuned your cache is, because there's nothing to actually reuse. Don't chase a "bad" ratio on a bin like that; look at whether the bins that should be highly cacheable (rendered pages, entity render output) are actually performing well.

Interpreting a genuinely low ratio

When a bin that should be cacheable shows a stubbornly low hit rate, the usual suspects are: cache tags being invalidated more broadly than necessary (one content edit wiping far more cached items than it needed to), a max-age set too aggressively short, or simply not enough memory allocated to the backend so items get evicted before they're ever reused. Diagnosing which one it is usually means correlating the hit-rate drop with your site's actual activity — a spike in misses right after a batch content import, for instance, points squarely at overly broad cache tag invalidation rather than a memory or configuration problem.

Quick check: the render cache bin shows a 92% hit rate, but a bin holding per-user "last seen" timestamps shows 3%. Should you be concerned about the 3% bin? (Answer: no — that data is unique per user by nature, so there's essentially nothing to reuse across requests. A near-zero hit rate there is expected and not a sign anything is misconfigured; the 92% on the render bin is the number that actually reflects your caching effectiveness.)

Key takeaways

  • Hit/miss ratio = hits / (hits + misses) — measure it from the backend itself (Redis's INFO stats, Memcache's stats command) for the most reliable numbers.
  • Backend stat counters are cumulative — sample twice over a known interval to get a "right now" rate, not a lifetime average.
  • A low hit rate is expected and fine for genuinely per-request-unique data; it's only a problem on bins that should be highly cacheable.
  • A drop in hit rate that correlates with a specific event (a content import, a deploy) usually points to overly broad cache tag invalidation, not a backend or memory problem.

Coming up next

With caching itself well understood and measured, we turn next to the database layer directly — optimizing the queries and indexes that everything else, cached or not, ultimately depends on.