We added a Redis cache to speed things up. It made every request slower.

What we cached:

  • User profiles (read on every request, but updated so often that entries were stale almost immediately)
  • Shopping cart (user-specific, volatile)
  • Real-time inventory counts

The problem:

  • Cache hit rate: 3%
  • 97% of requests: cache miss + DB query anyway
  • Every request paid the network round-trip to Redis: ~2ms
  • Plus serialization/deserialization: ~5ms
  • Net result: ~7ms of pure overhead on nearly every request — slower than no cache

What we should have cached:

  • Product catalog (read-heavy, rarely changes)
  • Category tree (static)
  • Feature flags (global, rarely changes)
  • Computed aggregations (expensive to calculate)

Cache math:

Benefit per request = (hit_rate × db_latency_saved) - cache_overhead

The overhead applies to every request.
The saving applies only to hits.
If benefit < 0, the cache is hurting you.

Fixed version:

  • Removed volatile data from cache
  • Added static content with long TTL
  • Hit rate: 3% → 85%
  • P50 latency: 150ms → 40ms

Lesson: Cache read-heavy, rarely-changing data. Not write-heavy, volatile data. Profiling the request path before adding infrastructure is the first thing we do in our DevOps engagements — the cheapest cache is the one you never needed.


← Back to Lessons Learned