Skip to main content
When the same item is requested repeatedly, reading it from the database each time is wasteful. Consider a public figure on your app—like Lionel Messi or Cristiano Ronaldo—whose post is viewed millions of times. The database can be hammered with identical queries for the same photo. A cache placed in front of the database solves this by serving popular items from a small, extremely fast store.
The image illustrates a system architecture flow, depicting an app accessing data with an added cache layer between the app and the database to improve performance.
Why use a cache?
  • Reads from an in-memory cache often complete in under 1 ms; the same read from a typical database may take 20–30 ms or more.
  • Under heavy load, those milliseconds multiply into significantly higher throughput and lower cost.
Typical request flow with a cache (using Redis as an example):
  1. A request arrives for a trending photo.
  2. The application checks Redis first:
    • If Redis contains the item → cache hit: return value from Redis; skip the database.
    • If Redis does not contain the item → cache miss: query the database, write the result back into Redis (often with a TTL), then return the response. Future requests will hit the cache.
The image illustrates how a cache system using Redis works between a mobile application and a database. It shows the process of requesting photos, with Redis checking if the data exists before querying the database.
Example: cache-aside (lazy population) in Python
What to cache
  • Cache items that are:
    • Small in size (so the cache stays memory-efficient)
    • Read frequently (high read-to-write ratio)
    • Updated rarely (reduces invalidation complexity)
The image illustrates a caching process using an app and Redis to store a trending photo record and a popular profile card. It highlights what data is stored in the cache for quick access.
Sessions and caches
  • Login sessions must be stored in a shared store accessible to all app servers. Redis is often used for both sessions and caching because session data is small, read on nearly every request, and requires low latency.
  • Keep session keys and cached keys properly namespaced to avoid collisions (for example: session:{user_id} vs profile:{user_id}).
Redis is commonly used for both caching hot application data and as a session store. Use clear namespaces for session keys and cache keys to avoid accidental collisions.
Cache coherence: the trade-offs Caching introduces a second copy of data (database + cache). Inconsistency can arise when one copy changes and the other does not. Example problem: a photo deleted from the database still exists in Redis and continues to be served to users until it expires or is invalidated.
The image illustrates the flow of data between a mobile app, Redis cache, and a database, highlighting an issue where data is still served from the cache after being deleted from the database.
Common caching strategies and trade-offs Key practices
  • Use clear key naming: photo:{id}, profile:{id} to make invalidation and debugging easier.
  • Apply sensible TTLs for items where eventual consistency is acceptable.
  • Combine explicit invalidation on writes/deletes with TTLs to limit inconsistency windows.
  • Test failure modes: cache node loss, partial updates, and race conditions (e.g., double writes).
  • Monitor cache hit/miss rates, memory usage, and eviction count to tune policies.
Cache invalidation is one of the hardest problems in distributed systems. Choose a strategy (cache-aside vs write-through vs write-behind) based on your consistency, latency, and complexity requirements, and test failure scenarios (cache node failure, incomplete invalidation).
Summary
  • Caching (e.g., Redis) dramatically accelerates reads for small, hot, infrequently changing data.
  • The cache-aside pattern is simple and widely used: check cache → on miss read DB → populate cache.
  • Design for cache consistency using TTLs, explicit invalidation, or read/write caching strategies that align with your correctness and latency needs.
Links and references
  • Redis
  • Martin Kleppmann, “Designing Data-Intensive Applications” – section on caching and consistency
  • Patterns: Cache-aside, Read-through, Write-through, Write-behind — search for implementation guides in your language or framework of choice

Watch Video