What is Caching — Simple Explanation with Examples
Caching is a technique that stores copies of frequently accessed data in a temporary storage layer for faster retrieval, reducing latency and lowering load on backend systems.
In this guide, you’ll learn how caching works at every level of the stack — from browser to database — and how to implement it effectively in your applications. Caching is the single most impactful performance optimization available.
Why Caching Exists — The Problem It Solves
Fetching data from its source is expensive:
- Database queries: Reading from disk (10–50ms per query)
- API calls: Network round-trips (50–500ms per request)
- File reads: Disk I/O for static assets
- Computation: Generating the same response repeatedly (templates, reports)
Caching avoids this cost by keeping a copy of the result somewhere faster. The first request pays the full cost; subsequent requests pay almost nothing.
The 80/20 Rule
Most applications follow the 80/20 rule of access: 80% of requests hit 20% of the data. A popular blog post, a trending product, or a user’s session data is accessed far more often than other data. Caching exploits this pattern by keeping hot data close to the user.
The Analogy — Post-It Notes
Imagine you’re studying for an exam from a 500-page textbook. Every time you need a formula, you open the book, find the page, and read it. That takes time.
Now imagine you write the key formulas on post-it notes and stick them on your desk. You can glance at them instantly without opening the book.
Caching is the same:
- Textbook = origin (database, disk, API)
- Post-it note = cache (memory, edge server)
- Exam formulas = frequently accessed data
As you memorize formulas, you might remove the post-its. That’s cache eviction.
Types of Caches
| Cache Type | Storage | Speed | Persistence | Example |
|---|---|---|---|---|
| In-memory | RAM | Nanoseconds | No (volatile) | Redis, Memcached |
| Disk | SSD/HDD | Milliseconds | Yes | Database query cache |
| CDN | Edge servers | 10-50ms | Configurable | Cloudflare, Akamai |
| Browser | Local disk | Milliseconds | Yes (cookies) | HTTP cache |
| DNS | Resolver servers | 10-100ms | Configurable (TTL) | OS resolver cache |
Cache Strategies
TTL-Based (Time-To-Live)
Data is cached for a fixed duration, then expires. Simple and predictable.
# Redis — cache API response for 5 minutes
import redis
r = redis.Redis()
def get_user(user_id):
cache_key = f"user:{user_id}"
cached = r.get(cache_key)
if cached:
return json.loads(cached)
user = db.query("SELECT * FROM users WHERE id = ?", user_id)
r.setex(cache_key, 300, json.dumps(user)) # TTL: 300 seconds
return userLRU (Least Recently Used)
When the cache is full, evict the least recently accessed item. Good for unpredictable access patterns.
from functools import lru_cache
@lru_cache(maxsize=128)
def compute_expensive_result(n):
"""Simulate expensive computation (e.g., Fibonacci)."""
if n < 2:
return n
return compute_expensive_result(n-1) + compute_expensive_result(n-2)
# First call: computes and caches
result = compute_expensive_result(35)
# Second call: returns from cache (nanoseconds)
result = compute_expensive_result(35)Write-Through
Data is written to the cache AND the database simultaneously. Ensures cache always has fresh data, but adds latency to writes.
def write_through(user_id, data):
"""Write data to both cache and database."""
r.setex(f"user:{user_id}", 300, json.dumps(data)) # Write to cache
db.execute("UPDATE users SET ... WHERE id = ?", data, user_id) # Write to DBCache-Aside (Lazy Loading)
Application checks the cache first. If miss, loads from database and populates cache. Most common pattern.
def get_product(product_id):
# 1. Check cache
cached = r.get(f"product:{product_id}")
if cached:
return json.loads(cached)
# 2. Cache miss — load from database
product = db.query("SELECT * FROM products WHERE id = ?", product_id)
# 3. Populate cache for next time
r.setex(f"product:{product_id}", 3600, json.dumps(product))
return productHTTP Caching Headers
Browsers and CDNs use HTTP headers to decide what and how long to cache.
HTTP/1.1 200 OK
Content-Type: text/html
Cache-Control: public, max-age=3600, s-maxage=86400
ETag: "abc123"
Last-Modified: Mon, 20 Jun 2026 10:00:00 GMT| Header | Purpose |
|---|---|
Cache-Control: public | Any cache (CDN, browser) can store |
Cache-Control: private | Only browser cache (not CDN) |
max-age=3600 | Cache for 1 hour |
s-maxage=86400 | CDN cache for 1 day (overrides max-age) |
ETag | Version identifier — client asks “is this still fresh?” |
Last-Modified | Timestamp for conditional requests |
Express.js Example
const express = require('express');
const app = express();
app.get('/api/posts', (req, res) => {
res.set('Cache-Control', 'public, max-age=300');
res.json(posts);
});
app.get('/api/user/profile', (req, res) => {
res.set('Cache-Control', 'private, max-age=60');
res.json({ name: 'Alice', email: 'alice@example.com' });
});Redis/Memcached Example
Redis: Advanced Caching
import redis
import json
r = redis.Redis(host='localhost', port=6379, decode_responses=True)
# Set cache with TTL
r.setex('homepage:featured', 1800, json.dumps(featured_products))
# Get cache
data = r.get('homepage:featured')
if data:
return json.loads(data)
# Cache invalidation (delete specific keys)
r.delete('homepage:featured')
# Cache with tags (track related keys)
r.sadd('tag:category:electronics', 'product:1', 'product:2')
r.sadd('tag:category:electronics', 'product:3')
# Invalidate all products in a category
for key in r.smembers('tag:category:electronics'):
r.delete(key)Memcached: Simple Key-Value
import memcache
mc = memcache.Client(['127.0.0.1:11211'])
# Set cache
mc.set('user:42', user_data, time=3600)
# Get cache
data = mc.get('user:42')
# Multi-get (efficient batch retrieval)
users = mc.get_multi(['user:1', 'user:2', 'user:3'])Browser Cache Example
Browsers cache static assets (images, CSS, JS) aggressively. Developers control this via headers or the HTML meta tag:
<!-- Disable caching for development -->
<meta http-equiv="Cache-Control" content="no-cache, no-store, must-revalidate">
<!-- Force browser to fetch latest version -->
<link rel="stylesheet" href="/css/app.css?v=20260620">Web Performance Impact
| Optimization | Typical Improvement |
|---|---|
| Browser cache (static assets) | 2-5x faster repeat visits |
| CDN cache | 50-80% latency reduction |
| Database query cache | 10-100x faster reads |
| In-memory cache (Redis) | 1000x faster than disk queries |
Real-World Numbers
Without caching:
User → DNS (50ms) → Server (200ms) → Database (50ms) → Response
Total: ~300ms per requestWith caching:
User → CDN cache (20ms) → Response
Total: ~20ms per request (15x faster)Common Use Cases
1. Web page acceleration
Cache HTML, CSS, JS, and images on CDNs and browsers. Repeat visitors load pages in milliseconds instead of seconds.
2. Database query caching
Cache frequent queries (product listings, user profiles) in Redis. Reduces database load by 90%+.
3. API response caching
Third-party API data that changes hourly (exchange rates, weather) can be cached to avoid rate limits and speed up responses.
4. Session storage
Store user sessions in Redis instead of the database. Fast reads/writes with automatic expiry.
5. Computed results
Cache expensive computations (report generation, image processing, machine learning inference) so they’re computed once and reused many times.
FAQ
Related Terms
CDN, Redis, Memcached, Database Index, DNS
Built by the developers of DodaTech
Doda Browser, DodaZIP & Durga Antivirus Pro