▲IkhlasIT StudioWarming up the planet
Now booking — 3 engineering slots for Q3. Free 30-minute consult →
Home / Blog / Performance

The cache layer nobody measured

Hit ratios, stampede protection and the three-line change that took our p95 from 900ms to 120ms.

The situation

A dashboard API took 900ms at p95. The database was healthy, the queries were indexed, the instance was not under pressure. Nobody could explain why it was slow.

Nobody had ever looked at the cache. When we finally did, the hit ratio was 31% — which is worse than having no cache at all, because you pay for the lookup and get a miss.

Why a bad cache is slower than no cache

Every request paid a network round-trip to Redis, serialised a result, wrote it back, then missed on the next request and hit PostgreSQL anyway. The cache was pure overhead plus a serialisation cost.

Three changes

  • Key by shape, not by URL. dash:{tenantId}:{range}:{filtersHash} instead of the raw query string. Half the keys were one-off variants nobody ever requested twice.
  • TTL with jitter. A flat 60-second TTL means every key expires in the same second. Adding +/-20% random jitter smoothed the miss curve completely.
  • Stampede protection. A single-flight lock so that when a popular key expires, one request repopulates it and the rest wait rather than all hammering the database.

Result: hit ratio 96%, p95 from 900ms to 120ms, database connections down 70%.

The lesson

If you have a cache, measure it on day one. INFO stats gives you keyspace_hits and keyspace_misses for free. A cache nobody measured is a cache nobody tuned — and usually worse than no cache at all.

Kafka consumer lag is not a metric — it is a symptomOur CI/CD checklist for teams of eleven
Want this on your system?

We build the thing the article is about

Thirty free minutes, an honest architecture opinion, and a fixed-scope quote.