Skip to content
Ravin Vasudev
Back to all articles

June 6, 2026 : 13 min read

Architecture Stack: Caching Strategies

Understanding caching: strategies to reduce latency and database load by serving frequently accessed data from fast, in-memory storage.

  • Architecture
  • Systems Design

This is a conversation between Alex (Engineering Manager) and Jordan (Senior Architect) exploring caching strategies in modern architecture.

Part 1: The Performance Problem

Alex: "Jordan, we've talked about breaking systems apart, managing distribution, and communicating via events. But I haven't heard much about pure performance. Like, when things get slow."

Jordan: "Great observation. That's where caching comes in. Let me paint a scenario."

Alex: "Okay."

Jordan: "You're Twitter. User clicks on their feed. Your service needs to fetch:

  1. User's followed accounts (query database)
  2. Recent posts from those accounts (query database)
  3. Like counts for each post (query database)
  4. Comment counts (query database)
  5. User preferences (query database)"

Alex: "That's a lot of database hits for one page load."

Jordan: "Right. And millions of users doing this simultaneously. Your database can't handle it. Queries take 5 seconds. Users wait. They get frustrated. They leave."

Alex: "That's a business problem."

Jordan: "Exactly. So what's the solution? Caching. Instead of querying the database every time, store frequently accessed data in super-fast memory. Next time someone asks, you answer from memory."

Alex: "And memory is faster than database?"

Jordan: "Orders of magnitude. A database query takes milliseconds to seconds. A memory lookup takes microseconds. Huge difference at scale."


Part 2: What Is Caching?

Alex: "Define caching for me."

Jordan: "Caching is storing copies of frequently accessed data in a faster, more accessible location. So that repeated requests for that data are served quickly without hitting the original source."

Alex: "What's the 'faster location'?"

Jordan: "Usually in-memory storage. RAM. Your computer's memory. Super fast but limited size. You can't cache everything, so you cache the hot data: the stuff people access frequently."

Alex: "How does it work?"

Jordan: "Simple flow: request comes in. Check if the data is in cache. If yes (cache hit), return it instantly. If no (cache miss), fetch from database, store in cache, return to user. Next request for same data hits the cache."

Alex: "What about when data changes?"

Jordan: "Good question. That's the challenge. If you're caching a user's profile and they change their bio, the cache has the old bio. You need to invalidate the cache (remove it) so the next request fetches fresh data."

Alex: "How do you know when to invalidate?"

Jordan: "That's the art. Multiple strategies depending on your use case."


Part 3: Problems Caching Solves

Alex: "What concrete problems does caching solve?"

Jordan: "Several:

Latency: Queries hitting a remote database take time. The network is slow. Parsing the result is slow. Returning data is slow. Caching removes all that. Memory is local and fast.

Database Load: If every user sees 10 queries on their page load, and you have 1M concurrent users, that's 10M queries per second. Your database explodes. Caching reduces that to maybe 1M queries per second (only cache misses and writes).

Scalability: Without caching, you need massive database infrastructure. With caching, your database is smaller and cheaper.

User Experience: Slow pages make users angry. Fast responses keep them happy. Caching is the difference between 5-second page loads and 100-millisecond page loads."

Alex: "That's significant."

Jordan: "It is. Large-scale systems are built on caching."


Part 4: Why This Matters

Alex: "In business terms?"

Jordan: "Directly impacts revenue. Studies show every 100ms delay in page load costs 1% of conversions. So if caching gets you from 5-second to 500-millisecond page loads, you're protecting millions in revenue."

Alex: "Performance is literally money?"

Jordan: "Yes. At scale, definitely. A slow system loses users. Users go to competitors."

Alex: "What else?"

Jordan: "Infrastructure costs. Databases that can serve 1M queries per second are incredibly expensive. If caching reduces that to 10% of queries hitting the database, you've cut infrastructure spend dramatically."

Alex: "So caching is business infrastructure, not just engineering optimization?"

Jordan: "Exactly right."


Part 5: The Traditional Approach (No Caching)

Alex: "What does a system without caching look like?"

Jordan: "Every request hits the database or API. User wants their profile picture. Query database. User wants feed. Query database. User wants recommendations. Query API. All synchronous, all slow."

Alex: "That's simple, at least?"

Jordan: "Yes. Simple but fragile. As load increases, everything slows down. More users means more queries means slower responses. It's not a linear degradation either. Once the database gets busy, response times skyrocket."

Alex: "Why?"

Jordan: "Database connection pooling. Once you're maxed out on connections, new requests queue. They wait. First-come-first-served. Slower queries block faster ones. The whole system becomes latency-sensitive. One slow query affects everyone."

Alex: "So without caching, you're constrained by database performance?"

Jordan: "Completely. It's the bottleneck."


Part 6: Caching Benefits

Alex: "What do we gain by caching?"

Jordan: "Multiple dimensions:

Speed: Fastest possible response. Memory lookups are nanoseconds.

Reduced Database Load: Fewer queries hitting the database means cheaper infrastructure.

Better User Experience: Fast pages, fast API responses, smooth interactions.

Scalability: Can handle more traffic without proportionally increasing database infrastructure.

Cost Efficiency: Less database load means smaller instances, fewer replicas, lower cloud bills.

Resilience: If database is slow or temporarily unavailable, cache can serve requests.

Geographic Distribution: Cache data near users (edge caches). Users in Europe get fast responses from European cache instead of querying US database."

Alex: "That last one is new."

Jordan: "Yes. CDNs (Content Delivery Networks) cache content at edge locations around the world. When a user in Australia requests something, they get it from the nearest cache, not from your central data center."


Part 7: Key Caching Patterns & Strategies

Alex: "What are the main approaches?"

Jordan: "Several patterns:

Cache-Aside (Lazy Loading): Application checks cache first. Miss? Fetch from database and populate cache. Simple but adds latency on misses.

Write-Through: On write, update database AND cache simultaneously. Read always hits cache. Keeps cache fresh but write latency increases.

Write-Behind (Write-Back): Write to cache immediately, asynchronously write to database. Fast writes but risk losing data if cache crashes before database write completes.

Refresh-Ahead: Before cache expires, proactively refresh it in background. Prevents 'cold cache' (new request sees stale data while refresh happens).

Invalidation: When data changes, remove from cache. Next request fetches fresh. Simple but can cause cache misses.

TTL (Time-To-Live): Cache expires automatically after N seconds. Guarantees freshness within N seconds. Simple but not instantly fresh."

Alex: "Which do we use?"

Jordan: "Depends. For user profiles, write-through or TTL. For recommendations, cache-aside or refresh-ahead. For analytics, eventual consistency with longer TTLs is fine."


Part 8: Cache Levels & Architectures

Alex: "You mentioned caches at different levels?"

Jordan: "Yes. Multiple layers:

Browser Cache: Browser stores CSS, JavaScript, images locally. User reloads page, resources come from disk cache, instant.

CDN Cache: Content Delivery Network caches images, static files at edge locations globally. User in Japan gets content from Tokyo CDN.

Application Cache: In-memory cache within your service. Redis, Memcached. Stores computed data, query results, sessions.

Database Cache: Some databases (like Redis as a primary store) ARE the cache. Durable memory store.

Query Cache: Database query results cached. PostgreSQL has this. Faster queries without application code.

Browser-Local Storage: Service workers cache API responses for offline use or faster reloads."

Alex: "That's multi-layer."

Jordan: "You use all of them at enterprise scale. Each layer optimizes different parts of the path from user to data."


Part 9: Implementation Strategy

Alex: "How do you actually build a cached system?"

Jordan: "Start by identifying what to cache:

  1. What data is accessed frequently?
  2. What data is expensive to compute or fetch?
  3. How fresh does it need to be?

Frequent + Expensive + Can tolerate staleness = Good cache candidate."

Alex: "How do you find that?"

Jordan: "Monitoring and profiling. Instrument your application. Log every database query and its duration. See which queries are called most often and which are slowest. Cache those."

Alex: "Then what?"

Jordan: "Pick a cache technology. Redis is most common. Fast, flexible, supports many data structures. Set up a Redis instance (or cluster for high availability). Choose a caching strategy based on your needs."

Alex: "How do you avoid stale data?"

Jordan: "Several approaches:

  1. TTL: Expire cache after N seconds. Automatic but not instantly fresh.
  2. Invalidation: When data changes, explicitly remove from cache. Requires coordination.
  3. Event-driven invalidation: When data changes (via event), remove from cache. Needs event system.
  4. Write-through: Update cache when you update database. Requires careful orchestration.
  5. Hybrid: Short TTL plus event-driven invalidation. Paranoid but fresh."

Alex: "Hybrid sounds complex."

Jordan: "It is. But for critical data where staleness has consequences (inventory counts, balances), it's necessary."


Part 10: Cache Invalidation Complexity

Alex: "You said cache invalidation is hard?"

Jordan: "There's a famous quote: 'There are only two hard things in Computer Science: cache invalidation and naming things.'"

Alex: "Why is it hard?"

Jordan: "Consider this: You cache 'user.profile.email'. User changes email. You delete from cache. But what if they also have 'recently.viewed.users' cached, which includes their email? Now that's stale. What about 'user.friends' which contains their email? Cascade of invalidations."

Alex: "Oof."

Jordan: "Exactly. At scale, one change causes ripples. You either:

  1. Invalidate conservatively (delete more than necessary). Safe but wastes cache.
  2. Invalidate precisely (delete exactly what changed). Efficient but complex.
  3. Use TTL. Data is at most N seconds stale. Simple but not fresh."

Alex: "Most systems use TTL?"

Jordan: "Yes. Simplest approach. Usually with short TTLs (seconds to minutes) for critical data, longer for non-critical."


Part 11: Cache Consistency & Trade-offs

Alex: "Is cached data ever wrong?"

Jordan: "Always, technically. It's stale as soon as the original data changes. The question is: how stale is acceptable?"

Alex: "How do you decide?"

Jordan: "For each cached item, ask: What's the cost of serving stale data? If it's high (account balance, order status), short TTL or invalidation. If it's low (trending topics, recommendation suggestions), longer TTL is fine."

Alex: "So it's a business decision?"

Jordan: "Exactly. Engineering supports it, but business needs define the SLA."

Alex: "What about write consistency?"

Jordan: "If you write to cache but database fails, you have cached data that doesn't match database. On reads, you get cache. But it's wrong. Solutions:

  1. Write-through: Fail fast if database fails. Catch errors early.
  2. Write-behind with persistence: Write to cache and a durability layer (message queue). Retry to database later.
  3. Accept inconsistency: Cache is eventually consistent. Business accepts that risk."

Alex: "That's a spectrum."

Jordan: "Yes. Stronger consistency costs more in latency or complexity."


Part 12: Cache Sizes & Eviction Policies

Alex: "You can't cache everything. What happens when cache is full?"

Jordan: "You need an eviction policy. When cache fills, what gets removed?

LRU (Least Recently Used): Remove item not accessed for longest time. Most items become stale infrequently, so this works well.

LFU (Least Frequently Used): Remove item accessed least often. Different distribution: sometimes accessed once but stuck around.

FIFO (First In First Out): Remove oldest item. Simple but potentially bad: old items might be hot.

TTL: Remove items past their expiration time. Automatic freshness guarantee."

Alex: "Do we configure this?"

Jordan: "Yes. Redis lets you set maxmemory-policy. Most systems use LRU or a hybrid."

Alex: "What's the memory requirement?"

Jordan: "Depends on what you cache. A 2GB Redis instance can cache thousands of user profiles. For a service with 1M users, 2GB isn't enough if you cache all profiles. You'd cache hot users or use distributed caching across multiple Redis instances."


Part 13: Distributed Caching

Alex: "At scale, do you have one cache?"

Jordan: "No. Single cache instance becomes the bottleneck. Distributed caching: multiple cache instances across machines."

Alex: "How do you keep them in sync?"

Jordan: "Usually you don't. You use consistent hashing. Each cache stores a subset of data. When you want to cache 'user.123.profile', hashing determines which cache instance stores it. Next request for same data hashes to same instance."

Alex: "What if a cache instance dies?"

Jordan: "Others take over the load. Data is lost but it can be refetched. That's acceptable because cache is ephemeral."

Alex: "So distributed cache is like distributed systems?"

Jordan: "Exactly. Same principles. Multiple independent nodes, eventual consistency, resilience through redundancy."


Part 14: Cache Warming & Cold Starts

Alex: "What's cache warming?"

Jordan: "When you restart a service, its cache is empty. First requests are cache misses, hitting the database. Database gets slammed. Service is slow. Bad user experience."

Alex: "How do you avoid it?"

Jordan: "Cache warming: on startup, preload the cache with hot data. Load top 1000 users, trending items, etc. Startup takes longer but cache is warm. Requests are fast immediately."

Alex: "How do you know what to warm?"

Jordan: "Usage patterns. Monitor most accessed items. On deployment, load those into cache before accepting traffic."

Alex: "Sounds manual?"

Jordan: "Can be automated. Deployment scripts can run cache-warming queries. Or use a side service that continuously populates cache with hot data."


Part 15: Monitoring & Debugging

Alex: "How do you know if caching is working?"

Jordan: "Key metrics:

Cache Hit Ratio: Percentage of requests served from cache. Target is high (90%+). If ratio is low, either cache is too small or invalidation is too aggressive.

Cache Size: Monitor actual memory used. If cache is full (LRU evicting constantly), consider growing it.

Cache Latency: Time to retrieve from cache. Should be microseconds. If it's milliseconds, cache itself is bottleneck.

Database Queries: Count queries hitting database. Should drop significantly with caching.

Stale Data Incidents: Track cases where stale cache caused issues. Adjust TTL or invalidation strategy."

Alex: "How do you debug cache issues?"

Jordan: "Common problems:

Cache Miss Storm: After invalidation or restart, all requests are cache misses. Database gets hammered. Solution: cache warming or gradual request distribution.

Stale Cache: Data changed but cache wasn't invalidated. Solution: shorten TTL or add explicit invalidation.

Memory Leak: Cache grows infinitely. Solution: check TTL is working, eviction is configured.

Cascading Invalidation: One change causes hundreds of items to be invalidated. Solution: design cache keys carefully to minimize invalidation blast radius."

Alex: "These are real problems?"

Jordan: "Very real. At scale, cache bugs cause major incidents."


Part 16: When to Cache & When Not To

Alex: "Give me the decision framework."

Jordan: "Cache when:

  • Data is read frequently, written infrequently
  • Database or API is slow
  • You can tolerate brief staleness
  • Memory is available
  • Consistency requirements are not super strict

Don't cache when:

  • Data changes frequently and strong consistency is required
  • Memory is limited
  • Cache invalidation is extremely complex
  • Data is sensitive (security implications of stale state)
  • Cache would be unused (low hit ratio)"

Alex: "So it's about read-to-write ratio and consistency requirements?"

Jordan: "Exactly. High read-to-write and weak consistency requirements = great for caching."


Part 17: The Modern Caching Ecosystem

Alex: "What tools do we use?"

Jordan: "Several options:

Redis: Dominant. In-memory data store supporting strings, lists, sets, hashes, sorted sets. Very fast. Supports persistence and cluster mode for HA.

Memcached: Simpler than Redis. Just key-value store. Slightly faster but less flexible.

DynamoDB DAX: AWS managed cache layer for DynamoDB. Specifically designed for that database.

Application-Level Caching: Some frameworks have built-in caching (Spring Cache, Django cache). Simpler but limited.

CDN (Cloudflare, CloudFront): Caches static content at edges globally.

Database Query Cache: Some databases have built-in caching (Query Results Cache)."

Alex: "Redis sounds most flexible?"

Jordan: "Yes. It's the default choice for most companies. Mature, well-understood, supports many patterns."


Part 18: Bridging to the Next Layer

Alex: "We've covered L1 now (Services & Data): Microservices, Distributed Systems, Event-Driven, and Caching."

Jordan: "Right. Now L2 is Platform Delivery: the infrastructure to run all this at scale. Kubernetes orchestrates containers. ArgoCD handles deployments. Helm packages applications. All the operational machinery."

Alex: "So L1 is 'how to design' and L2 is 'how to operate'?"

Jordan: "Exactly. You need both."


Part 19: The Bottom Line

Alex: "If I pitch this to leadership?"

Jordan: "Caching is the key to performance at scale. Instead of databases handling every request, cached data serves the majority. This means: users get 10-100x faster responses, infrastructure costs drop by 50-80%, and the service can handle 10x more traffic. It's not optional at scale, it's essential."

Alex: "And the trade-off?"

Jordan: "Slight staleness in data. You need to think about cache invalidation and consistency. It adds operational complexity. But the benefits far outweigh the cost."

Alex: "Ready for Platform Delivery?"

Jordan: "Absolutely. That's where we make this all work."


Key Takeaways

| Aspect | Details | | --------------------- | ----------------------------------------------------------------------------------- | | Core Concept | Store frequently accessed data in fast memory to reduce latency and database load | | Primary Benefit | 10-100x faster responses, 50-80% infrastructure cost reduction, massive scalability | | Best For | High-read systems, databases with query load, performance-critical applications | | Main Challenge | Cache invalidation, handling staleness, consistency guarantees | | Key Patterns | Cache-Aside, Write-Through, Write-Behind, Refresh-Ahead, TTL, Invalidation | | Common Strategies | LRU/LFU eviction, distributed caching, cache warming, multi-layer architecture | | Prerequisites | Monitoring, understanding access patterns, infrastructure maturity | | Mindset Shift | Trade consistency for speed; fresh is good, but eventual freshness often sufficient |


L1 Series Complete

  1. Microservices (organizational breakdown)
  2. Distributed Systems (technical foundations)
  3. Event-Driven Architecture (communication patterns)
  4. Caching Strategies (performance optimization) ← You are here

Next up: L2 – Platform Delivery

  • AWS (compute, storage, networking)
  • Kubernetes (container orchestration)
  • ArgoCD (GitOps deployments)
  • Helm (application packaging)
  • DevSecOps (security automation)

Ready to move to L2 and explore Platform Delivery? Or would you like to go deeper into any L1 concepts?