Caching Fundamentals in System Design
Learn Caching from a System Design perspective. This guide explains why caching is essential, cache architectures, cache strategies, cache eviction policies, distributed caching, Redis, Memcached, CDN caching, Spring Boot caching, and real-world examples from Amazon, Netflix, Uber, and Banking systems.
Introduction
Imagine an e-commerce website where 10 million users search for the same iPhone every day.
Without caching, every request follows this path:
User
↓
Spring Boot API
↓
Database
↓
Response
Now imagine:
- 100,000 users request the same product every minute.
- Every request queries the database.
- Database CPU reaches 100%.
- Response time increases from 20ms to 2 seconds.
The solution?
Caching.
Caching stores frequently accessed data in fast memory, allowing applications to respond in milliseconds instead of querying the database repeatedly.
Almost every large-scale application—including Amazon, Netflix, Uber, Google, Facebook, and Banking platforms—relies heavily on caching.
Learning Objectives
After completing this article, you will understand:
- What is Caching?
- Why Caching is Important
- Cache Architecture
- Cache Hit & Cache Miss
- Cache Strategies
- Cache Eviction Policies
- Distributed Caching
- Redis
- Memcached
- Spring Boot Caching
- CDN vs Application Cache
- Real-World Examples
What is Caching?
A Cache is a high-speed storage layer that stores frequently accessed data.
Instead of querying the database every time:
Database
↓
Cache
↓
Fast Response
Caches usually reside in memory (RAM), making them much faster than disk-based databases.
Why Caching?
Without Cache
flowchart TD
U[Users]
APP[Spring Boot]
DB[(Database)]
U --> APP
APP --> DB
Problems
- High database load
- Slow response time
- Increased infrastructure cost
- Poor scalability
With Cache
flowchart TD
U[Users]
APP[Spring Boot]
CACHE[(Redis Cache)]
DB[(Database)]
U --> APP
APP --> CACHE
CACHE --> DB
Benefits
- Faster response
- Reduced database load
- Better scalability
- Lower latency
Real-Time Example
Customer searches:
Apple iPhone 17
Without Cache
User
↓
Database Query
↓
300 ms
With Cache
User
↓
Redis
↓
5 ms
Cache Request Flow
flowchart LR
CLIENT["Client"]
APP["Spring Boot API"]
CACHE["Redis Cache"]
DB["Database"]
CLIENT --> APP
APP --> CACHE
CACHE -- "Cache Miss" --> DB
DB --> CACHE
CACHE -- "Cache Hit" --> APP
APP --> CLIENT
Cache Hit
A Cache Hit occurs when data already exists in the cache.
flowchart LR
USER["Client"]
APP["Spring Boot API"]
CACHE["Redis Cache"]
RESPONSE["Cached Response"]
USER --> APP
APP --> CACHE
CACHE --> RESPONSE
RESPONSE --> USER
Advantages
- Very fast
- No database query
- Low latency
Cache Miss
A Cache Miss occurs when data is not found in the cache.
flowchart LR
CLIENT["Client"]
APP["Spring Boot"]
CACHE["Redis Cache"]
DB["Database"]
CLIENT --> APP
APP --> CACHE
CACHE -- "Miss" --> DB
DB --> CACHE
CACHE --> APP
APP --> CLIENT
The retrieved data is stored in Redis for future requests.
Cache Lifecycle
flowchart TD
REQ["Request"]
LOOKUP["Cache Lookup"]
HIT{"Cache Hit?"}
RETURN["Return Data"]
DB["Database"]
STORE["Store in Cache"]
REQ --> LOOKUP
LOOKUP --> HIT
HIT -- Yes --> RETURN
HIT -- No --> DB
DB --> STORE
STORE --> RETURN
Cache Hit Ratio
Formula
Cache Hit Ratio
=
Cache Hits
÷
Total Requests
Example
900 Hits
100 Misses
↓
90% Hit Ratio
Higher hit ratio means better performance.
Types of Caching
| Cache Type | Purpose |
|---|---|
| Browser Cache | Static resources |
| CDN Cache | Global content delivery |
| Application Cache | Frequently used objects |
| Database Cache | Query optimization |
| Distributed Cache | Shared cache across services |
| CPU Cache | Hardware optimization |
Browser Cache
flowchart TD
B["Browser"]
C{"Cache Hit?"}
L["Load from Browser Cache"]
W["Request Website"]
B --> C
C -- Yes --> L
C -- No --> W
Stores:
- CSS
- JavaScript
- Images
CDN Cache
flowchart TD
U["Users"]
CDN{"CloudFront Cache Hit?"}
CACHE["Serve Cached Content"]
ORIGIN["Origin Server"]
U --> CDN
CDN -- Yes --> CACHE
CDN -- No --> ORIGIN
ORIGIN --> CACHE
CACHE --> U
Used for:
- Images
- Videos
- CSS
- JavaScript
Application Cache
flowchart TD
CLIENT["Client"]
APP["Spring Boot"]
CACHE{"Redis Cache"}
DB["Database"]
CLIENT --> APP
APP --> CACHE
CACHE -- Cache Hit --> CLIENT
CACHE -- Cache Miss --> DB
DB --> CACHE
CACHE --> CLIENT
Commonly cached:
- Product Details
- User Profiles
- Configuration
- Exchange Rates
Distributed Cache
In microservices,
multiple application instances share one cache.
flowchart TD
USERS["Users"]
LB["Load Balancer"]
APP1["Spring Boot 1"]
APP2["Spring Boot 2"]
APP3["Spring Boot 3"]
REDIS["Redis Cluster"]
DB["Database"]
USERS --> LB
LB --> APP1
LB --> APP2
LB --> APP3
APP1 --> REDIS
APP2 --> REDIS
APP3 --> REDIS
REDIS --> DB
Cache Strategies
Four major strategies are used in enterprise applications.
| Strategy | Description |
|---|---|
| Cache Aside | Application manages cache |
| Read Through | Cache loads data automatically |
| Write Through | Writes go to cache and database |
| Write Behind | Writes cached first, database updated later |
Cache Aside Pattern
Most popular strategy.
flowchart TD
APP["Application"]
CACHE{"Redis Cache"}
DB["Database"]
RETURN["Return Data"]
APP --> CACHE
CACHE -- "Hit" --> RETURN
CACHE -- "Miss" --> DB
DB --> CACHE
CACHE --> RETURN
Flow
- Check cache.
- Cache hit → return data.
- Cache miss → query database.
- Store in cache.
- Return response.
Read Through Cache
flowchart TD
APP["Application"]
CACHE["Cache"]
DB["Database"]
RETURN["Return Data"]
APP --> CACHE
CACHE -- "Cache Hit" --> RETURN
CACHE -- "Cache Miss" --> DB
DB --> CACHE
CACHE --> RETURN
Application communicates only with the cache.
Write Through Cache
flowchart TD
APP["Application"]
CACHE["Redis Cache"]
DB["Database"]
SUCCESS["Success Response"]
APP --> CACHE
CACHE --> DB
DB --> SUCCESS
Every write updates:
- Cache
- Database
Advantages
- Always consistent
Disadvantages
- Slightly slower writes
Write Behind Cache
flowchart TD
APP["Application"]
CACHE["Redis Cache"]
RESP["Return Success"]
QUEUE["Background Worker"]
DB["Database"]
APP --> CACHE
CACHE --> RESP
CACHE -. "Async Write" .-> QUEUE
QUEUE --> DB
Advantages
- Extremely fast writes
Disadvantages
- Risk of data loss if cache fails before persistence
Cache Eviction Policies
When memory becomes full,
the cache removes entries.
Common policies
| Policy | Description |
|---|---|
| LRU | Least Recently Used |
| LFU | Least Frequently Used |
| FIFO | First In First Out |
| TTL | Time-based expiration |
LRU Example
Cache
↓
A
B
C
↓
Access A
↓
Remove C
Least recently used item is removed.
TTL (Time To Live)
Example
User Profile
↓
TTL
↓
30 Minutes
After expiration,
Redis removes the entry automatically.
Redis Architecture
flowchart TD
USERS["Users"]
LB["Load Balancer"]
APP["Spring Boot"]
REDIS["Redis Cluster"]
DB["PostgreSQL"]
USERS --> LB
LB --> APP
APP --> REDIS
REDIS --> DB
Redis is:
- In-memory
- Extremely fast
- Distributed
- Highly available
Redis Data Structures
Redis supports
- String
- Hash
- List
- Set
- Sorted Set
- Stream
- Bitmap
Memcached
Another popular cache.
Advantages
- Very simple
- Extremely fast
Limitations
- Fewer data structures
- No persistence
- No replication
Redis vs Memcached
| Redis | Memcached |
|---|---|
| Persistent | No Persistence |
| Rich Data Types | Key-Value Only |
| Replication | Limited |
| Pub/Sub | No |
| Streams | No |
Banking Example
Frequently Cached
- Branch Details
- Currency Exchange Rates
- Interest Rates
- Product Information
Never Cache
- Account Balance
- Transactions
- Payment Status
Amazon Example
Cached Data
- Product Details
- Images
- Reviews
- Recommendations
Dynamic Data
- Inventory
- Pricing
- Cart
Netflix Example
Netflix caches:
- Movie Metadata
- Recommendations
- User Preferences
- CDN Content
Uber Example
Uber caches:
- Driver Locations
- Fare Estimates
- City Maps
- Surge Pricing
Spring Boot Architecture
flowchart TD
CLIENT["Client"]
LB["Load Balancer"]
APP["Spring Boot"]
CACHE["Redis Cache"]
DB["PostgreSQL"]
CLIENT --> LB
LB --> APP
APP --> CACHE
CACHE -- "Cache Miss" --> DB
DB --> CACHE
CACHE --> APP
APP --> CLIENT
Popular libraries
- Spring Cache
- Redis
- Caffeine
- Hazelcast
- Ehcache
Monitoring
Monitor
- Cache Hit Ratio
- Cache Miss Ratio
- Memory Usage
- Evictions
- Redis Latency
- TTL Expirations
- CPU Usage
- Network Traffic
Tools
- Redis Insight
- Datadog
- Grafana
- Prometheus
- CloudWatch
Common Mistakes
❌ Caching frequently changing data
❌ Very long TTL values
❌ Very short TTL values
❌ No cache invalidation strategy
❌ Storing huge objects
❌ Ignoring cache hit ratio
Best Practices
- Cache frequently read data.
- Avoid caching highly volatile data.
- Use Redis for distributed systems.
- Use TTL for automatic expiration.
- Monitor cache hit ratio regularly.
- Choose appropriate eviction policies.
- Use Cache Aside for most applications.
- Keep cached objects small.
- Secure Redis deployments with authentication and network isolation.
Common Interview Questions
What is a Cache?
A cache is a high-speed storage layer that stores frequently accessed data to reduce latency and database load.
What is the difference between a Cache Hit and a Cache Miss?
A Cache Hit occurs when the requested data is found in the cache. A Cache Miss occurs when the data is absent and must be fetched from the database.
Why is Redis commonly used for caching?
Redis is an in-memory data store that provides extremely low latency, supports rich data structures, replication, clustering, and persistence, making it ideal for distributed applications.
What is the Cache Aside pattern?
The application first checks the cache. If the data is missing, it loads it from the database, stores it in the cache, and returns it to the client.
Which data should not be cached?
Highly dynamic or security-sensitive data such as account balances, payment status, one-time passwords (OTPs), and real-time inventory should generally not be cached without careful consistency controls.
Summary
Caching is one of the most effective techniques for improving application performance and scalability. By storing frequently accessed data in fast memory, applications can dramatically reduce response times and minimize database load.
In this article, we covered:
- Caching fundamentals
- Cache Hit & Cache Miss
- Cache lifecycle
- Cache strategies
- Cache eviction policies
- Redis & Memcached
- Distributed caching
- Spring Boot integration
- Banking, Amazon, Netflix, and Uber examples
- Monitoring
- Best practices
A well-designed caching strategy enables systems to handle millions of requests with low latency, making caching a core building block of modern distributed system architecture.
Comments
Share a question, correction, or practical insight about this article.
Checking login status...
Loading approved comments...