How to Cache Function Results with Redis in Python

A RedisCache helper class caches function results using a decorator, with JSON serialization and TTL-based expiry.

Easy Python 3.9+ Aug 9, 2026 Caching & Redis 14 views 0 copies

Requires third-party packages — install first
pip install redis

Python code

36 lines
Python 3.9+
import redis
import json
from functools import wraps

class RedisCache:
    def __init__(self, host='localhost', port=6379, db=0, ttl=60):
        self.client = redis.Redis(host=host, port=port, db=db, decode_responses=True)
        self.ttl = ttl

    def cached(self, key_prefix):
        def decorator(func):
            @wraps(func)
            def wrapper(*args, **kwargs):
                key = f"{key_prefix}:{args}:{kwargs}"
                cached_value = self.client.get(key)
                if cached_value is not None:
                    print(f"Cache HIT for {key}")
                    return json.loads(cached_value)
                print(f"Cache MISS for {key}")
                result = func(*args, **kwargs)
                self.client.setex(key, self.ttl, json.dumps(result))
                return result
            return wrapper
        return decorator


cache = RedisCache(ttl=10)

@cache.cached("user")
def get_user(user_id):
    return {"id": user_id, "name": "Alice", "age": 30}


if __name__ == "__main__":
    print(get_user(1))
    print(get_user(1))

Output

stdout
Cache MISS for user:(1,):{}
{'id': 1, 'name': 'Alice', 'age': 30}
Cache HIT for user:(1,):{}
{'id': 1, 'name': 'Alice', 'age': 30}

How it works

The decorator cached wraps a function, computing a cache key from arguments. On a miss, it runs the function and stores the JSON result with setex, setting a TTL. On a hit, it reads the cached string and returns it with json.loads. Using functools.wraps preserves the original function metadata.

Common mistakes

  • Forgetting to set `decode_responses=True` so values are strings, not bytes.
  • Not including kwargs in the cache key, causing different calls to collide.
  • Using `json.dumps` without `ensure_ascii=False` when caching non-ASCII strings.
  • Assuming cache invalidation is automatic; TTL only expires old data

Variations

  1. Use a hash of arguments (e.g., `hashlib.md5`) to shorten cache keys.
  2. Add an optional `cache_none` flag to cache `None` results as well.

Real-world use cases

  • Caching database query results to reduce load on the primary instance.
  • Storing API responses for rate-limited external services to save quota.
  • Memoizing expensive computations like image processing in a web server.

Sponsored

Run locally

This sample needs third-party packages, so it cannot run in the browser IDE. Copy the code above, install the packages shown at the top, then run it in your own Python environment.

More from Caching & Redis

Related tutorials and quizzes for this topic.