How to Use lru_cache in Python for Cache-on-Miss Population
Demonstrates lru_cache to automatically populate cache on a miss and serve subsequent calls from cache, with cache info stats.
Python code
18 linesfrom functools import lru_cache
@lru_cache(maxsize=None)
def fetch_user(user_id):
"""Simulates a slow database fetch."""
print(f"Cache miss: fetching user {user_id} from database")
return {"id": user_id, "name": f"User {user_id}"}
if __name__ == "__main__":
user = fetch_user(1)
print(f"First call: {user}")
# Second call hits cache - no database message printed
user_again = fetch_user(1)
print(f"Second call: {user_again}")
# Verify cache stats
print(f"Cache info: {fetch_user.cache_info()}")
Output
Cache miss: fetching user 1 from database
First call: {'id': 1, 'name': 'User 1'}
Second call: {'id': 1, 'name': 'User 1'}
Cache info: CacheInfo(hits=1, misses=1, maxsize=None, currsize=1)
How it works
The @lru_cache decorator wraps fetch_user and automatically caches return values keyed by arguments. On the first call, a miss triggers the function body (printing the miss message) and stores the result. The second call with the same argument hits the cache and returns instantly without re-running the function. cache_info() reports hits, misses, maxsize, and current size, giving visibility into cache efficiency. This is a simple read-through pattern where the function itself is the data source.
Common mistakes
- Using `maxsize=None` for unlimited cache may cause memory growth; set a finite size for production.
- Assuming the function is not executed on cache hits — forget that side effects like print only run on misses.
- Forgetting that arguments must be hashable; lru_cache fails with unhashable types like lists.
- Not clearing the cache when underlying data changes, leading to stale values.
Variations
- Add a timeout-based refresh by manually clearing the cache with `fetch_user.cache_clear()`.
- Use `functools.cache` (Python 3.9+) for a simpler unlimited cache with the same behavior.
Real-world use cases
- Memoizing expensive database queries in a web service to reduce latency.
- Caching API responses in a microservice to avoid repeated network calls.
- Caching configuration or rarely-changing computed values in a data pipeline.
Sponsored
More from Caching & Redis
- Cache Asides in Python with a Read-Through Loader easy
- Cache Data in Redis with Python easy
- Cache Penetration Null Object Mock in Python medium
- Cache Stampede Prevention with SingleFlight in Python medium
- Cache Warming with Python: Preload Hot Keys easy
- Coalescing duplicate in-flight requests: one shared result for concurrent callers hard
Keep learning
Related tutorials and quizzes for this topic.