Cache-Aside
matureSummary
Application code manages the cache explicitly: check cache first, fetch from the database on a miss and populate the cache, and invalidate or update the cache on writes: with no automatic synchronisation layer between the two.
Problem
Database read latency and throughput limits cannot be addressed by adding more replicas alone; frequently-accessed data needs to be served from memory at sub-millisecond latency without hitting the database on every request.
Description
In the cache-aside pattern (also called lazy loading), the cache is treated as an optional acceleration layer rather than a primary store. The application owns all cache interactions. On a read: (1) check the cache for the key; (2) on a hit, return the cached value directly; (3) on a miss, execute the database query, write the result into the cache with a TTL, and return the result. On a write: update the database first, then either delete the cache key (invalidation) or write the new value (update-on-write).
Invalidation (deleting the key on write) is simpler and safer than update-on- write: the next read will re-fetch the authoritative value from the database. Update-on-write avoids the subsequent cache miss but introduces a race condition: two concurrent writers can write the cache in the wrong order, leaving a stale value until TTL expires. For this reason, invalidation is the default strategy.
TTL is the safety net: even if invalidation is missed (e.g., a direct DB write that bypasses application logic), the cached value expires eventually. TTL must be set based on how stale the data can be, not on cache memory pressure: those are separate concerns.
The cache-aside pattern is appropriate when data access is read-heavy, data changes at a predictable and manageable rate, and the application can tolerate stale reads within the TTL window. It is the simplest caching strategy and requires no additional infrastructure beyond a cache server.
Tradeoffs
Sub-millisecond reads from Redis vs 1–10ms from PostgreSQL
Significant reduction in read QPS to database at high hit rates (>90%)
TTL window means stale data is always possible; invalidation races exist
Cache invalidation logic scattered across write paths; must be maintained
Cache flush or cold start routes all traffic to database simultaneously
No improvement; database write path is unchanged
When to use
Read-to-write ratio is high (>80% reads) and data is accessed repeatedly
Cache hit rate is a function of access frequency; data that is read once per hour does not benefit enough from caching to justify the complexity
Data changes infrequently relative to how often it is read
High write rates invalidate cached values faster than they are served; the effective hit rate drops and cache provides less benefit
Application can tolerate stale reads within the TTL window
Cache-aside always has a staleness window between a write and cache invalidation or TTL expiry; this must be acceptable to the product
Cache misses can be absorbed: database can handle miss traffic
Cold start or a full cache flush results in all reads hitting the database simultaneously; database must survive this cold-start storm
When not to use
Data must always reflect the most recent write (financial balances, inventory)
Even a 100ms staleness window can cause double-spend or oversell; cache- aside is not appropriate without additional read-through consistency mechanisms
Write rate is comparable to read rate
High write rates cause constant cache invalidations; effective hit rate drops below the threshold where caching adds meaningful benefit
Cache and database divergence would cause data corruption
If acting on a cached value can cause an irreversible incorrect outcome, the safety margin must be weighed against the read performance benefit
Operational Requirements
Set TTL on every cached key; never cache without expiry
Keys without TTL accumulate indefinitely; stale data grows unboundedly and Redis memory fills until eviction begins evicting hot keys
Implement cache invalidation at every write path that mutates cached data
Missing a write path is the most common source of stale cache bugs; map every write operation to the set of cache keys it invalidates
Monitor cache hit rate and alert if it drops below baseline
Hit rate drop indicates either a new access pattern, a TTL that is too short, or a cache stampede condition: all require different responses
Implement mutex or probabilistic early expiry for high-traffic keys
Popular keys expiring under load cause thundering herd on the database; use a lock or jitter on TTL to prevent simultaneous misses
Characteristics
Technologies
Canonical
Alternatives
Relationships
Evolves to
Complements
Basis
Universally applied caching pattern with well-understood tradeoffs; stampede and invalidation race conditions are the primary failure modes and are thoroughly documented
Related Architecture Knowledge
Inbound: affects this entity
Geospatial radius query results for static reference points (store locations, service areas) can be cached since the underlying dataset changes infrequently relative to query frequency.
Full relationship →Search-heavy workloads cache popular queries and their result sets, absorbing the majority of search traffic from cache and reserving Elasticsearch or other search backends for uncached or freshness-sensitive queries.
Tradeoffs
- ·Search result caching is only correct when eventual consistency is acceptable : cached results may be slightly stale
- ·Cache key cardinality can be very high with many facet combinations: unbounded cache memory growth
- ·Cache invalidation on index updates requires either short TTL or event-driven invalidation
Vector search results for common queries can be cached with cache-aside to avoid repeated ANN index lookups for the same semantic query, trading some recall freshness for significant latency improvement.
Full relationship →Used In Architecture Scenarios
AI / RAG Application
A Retrieval-Augmented Generation (RAG) architecture that combines vector similarity search for semantic document retrieval with relational metadata filtering, using PostgreSQL with pgvector as the unified store for both embeddings and structured data. Redis provides a semantic cache to avoid redundant embedding model inference and reduce vector index query load for repeated or similar queries. Kafka manages the asynchronous embedding generation pipeline that keeps the vector index current as source documents are added or updated.
Multi-Tenant SaaS
A multi-tenant API gateway providing authentication, distributed rate limiting, request routing, payload transformation, and per-tenant usage analytics for API publishers. The hot path: authentication check, rate limit evaluation, and routing decision: must complete in under 1ms using Redis-only data structures to avoid proxying latency dominating upstream service response time. PostgreSQL stores tenant configuration, subscription plans, and API key definitions. Kafka receives API usage events for downstream billing and analytics. Configuration changes (rate limit updates, routing rule edits) must propagate to all gateway replicas without restart.
Read-Heavy Application
A CMS for publishing and serving structured content: articles, documentation, product pages, and localized variants: where read APIs serve 50–100x more traffic than editorial write APIs. PostgreSQL stores the content graph (articles, authors, categories, taxonomy) and workflow state (draft, in-review, scheduled, published). Redis caches published content objects for read APIs. Elasticsearch powers full-text content search with faceting and relevance ranking. Cache invalidation on publish must be fast and complete; N+1 query patterns on content relationship traversal are the dominant database performance risk during reads.
Marketplace Platform
An e-commerce order lifecycle platform handling cart, checkout, payment, fulfillment, and returns across a mixed read/write workload where product discovery is read-heavy, checkout is write-transactional, and fulfillment is event-driven. The saga pattern orchestrates multi-step checkout: reserve inventory → charge payment → confirm order → notify fulfillment. PostgreSQL owns order records and inventory with row-level locking; Redis holds session state and cart contents with sub-millisecond access; RabbitMQ delivers fulfillment notifications with dead-letter handling; Elasticsearch serves product search and order history with faceted navigation. CQRS separates the write command path from the read model: the order read model is denormalized for fast order history queries without joining across domain tables.
AI / RAG Application
A low-latency feature serving platform for ML model inference, providing both batch (offline) and real-time (online) feature access with strict training-serving consistency. Redis serves the hot feature cache with p99 latency targets below 5ms for online inference requests; PostgreSQL provides point-in-time feature lookups for offline training jobs with temporal consistency guarantees; Cassandra stores high-cardinality feature entities at write scale beyond PostgreSQL's single-primary ceiling; Kafka streams feature computation events from online feature pipelines to update the cache; Qdrant stores vector features for embedding-based model inputs and similarity lookups; ClickHouse serves feature analytics and drift monitoring across training dataset populations. Feature versioning is first-class: every feature value is tagged with a pipeline_version and computed_at timestamp to support model reproducibility and training-serving skew diagnosis.
Multi-Tenant SaaS
A multi-tenant SaaS architecture where multiple customers are served from a shared deployment, with PostgreSQL row-level security providing logical tenant isolation, Redis delivering per-tenant caching, and connection pooling managing the aggregate connection demand across tenant workloads. Tenant isolation, resource fairness, and operational simplicity are the three competing forces this architecture must balance.
Search-Heavy Application
A content platform architecture centered on Elasticsearch for full-text search, faceted navigation, and ranked results, with PostgreSQL as the transactional source of truth and Redis for session management and hot content caching. WAL-based CDC maintains index freshness by streaming PostgreSQL changes into Elasticsearch asynchronously. The core tension is between search index freshness, query performance, and index maintenance cost under high write volume.
Event-Driven System
A social activity feed architecture where user actions (posts, likes, comments, follows) fan out asynchronously to follower timelines. Redis stores hot feed data as pre-materialized lists per user, enabling O(1) timeline reads for the 99th percentile of users. Kafka carries fan-out work to async workers that write to follower Redis keys. PostgreSQL is the durable store for the social graph, posts, and user content. The system uses a hybrid fan-out model: fan-out-on-write for users with fewer than ~10,000 followers (low fan-out cost), fan-out-on-read for high-follower celebrity accounts where pre-materialized fan-out would saturate workers and Redis write bandwidth.
Event-Driven System
A video and audio streaming architecture where content ingestion triggers an async multi-variant transcoding pipeline, CDN delivery handles 95%+ of playback traffic, and Cassandra absorbs the write volume of per-user viewing history. Kafka decouples upload events from transcoding workers; MinIO stores raw and encoded assets; Redis maintains playback session state and view counters. The architecture must handle upload spikes without blocking delivery, and cache cold starts without cascading database load.
Marketplace Platform
A two-sided marketplace architecture serving buyers, sellers, listings, transactions, search, and notifications from a shared infrastructure, where multiple independent domains must coordinate without tight coupling. Event sourcing captures every state transition; the saga pattern orchestrates multi-step transactions (create order, reserve inventory, charge payment, notify seller) with compensating transactions for partial failures. Kafka decouples domain event publication from consumption; RabbitMQ handles notification fanout; Elasticsearch serves listing search; Redis caches listing display and session state.