Simple Redis Cache Helper in Python

Build a minimal Redis-backed cache with TTL, JSON serialization, and automated fetching to speed up repeated expensive lookups.

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

Requires third-party packages — install first
pip install redis

Python code

45 lines
Python 3.9+
import time
import redis
import json


class SimpleCache:
    def __init__(self, host="localhost", port=6379, db=0, default_ttl=60):
        self.client = redis.Redis(host=host, port=port, db=db, decode_responses=True)
        self.default_ttl = default_ttl

    def get(self, key):
        value = self.client.get(key)
        return json.loads(value) if value else None

    def set(self, key, data, ttl=None):
        self.client.set(key, json.dumps(data), ex=ttl or self.default_ttl)

    def delete(self, key):
        self.client.delete(key)


def fetch_with_cache(cache, key, expensive_function):
    cached = cache.get(key)
    if cached is not None:
        print(f"Cache hit for '{key}'")
        return cached

    print(f"Cache miss for '{key}' — fetching fresh data")
    data = expensive_function(key)
    cache.set(key, data)
    return data


def expensive_lookup(key):
    time.sleep(1)  # simulate slow work
    return {"key": key, "result": f"data for {key}", "computed_at": time.time()}


if __name__ == "__main__":
    cache = SimpleCache(default_ttl=5)
    for _ in range(3):
        result = fetch_with_cache(cache, "user:42", expensive_lookup)
        print(result)
        time.sleep(0.2)
    cache.delete("user:42")

Output

stdout
Cache miss for 'user:42' — fetching fresh data
{'key': 'user:42', 'result': 'data for user:42', 'computed_at': 1700000000.123456}
Cache hit for 'user:42'
{'key': 'user:42', 'result': 'data for user:42', 'computed_at': 1700000000.123456}
Cache hit for 'user:42'
{'key': 'user:42', 'result': 'data for user:42', 'computed_at': 1700000000.123456}

How it works

The SimpleCache class wraps the Redis client with decode_responses=True to return strings instead of bytes. json.dumps serializes the Python dict into a JSON string before storing, and json.loads converts it back on retrieval. The ex parameter in set sets an expiration time, defaulting to self.default_ttl when no TTL is provided. fetch_with_cache checks the cache first, and only calls the expensive function on a miss, reducing repeated work. This pattern is cache-aside: the application manages the cache and refreshes it on a miss.

Common mistakes

  • Forgetting `decode_responses=True`, causing `bytes` objects and errors when comparing strings.
  • Not handling `None` from `get()`, which indicates a cache miss.
  • Using a TTL that is too long, causing stale data in production.
  • Not closing the Redis connection, though the client handles it gracefully on exit.

Variations

  1. Use `cache.set(key, data, ttl=30)` to override the default TTL for specific keys.
  2. Add a `get_or_set` method that combines fetch-with-cache into a single call.

Real-world use cases

  • Caching database query results to reduce load on the primary database in a web application.
  • Storing API responses in Redis to avoid hitting rate limits on external services.
  • Sharing computed results across multiple app instances for faster startup and consistent data.

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.