Redis Cache Helper Class in Python with TTL

Build a DataHelper class that caches function results in Redis with a default TTL, using get_or_set and clear methods.

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

Requires third-party packages — install first
pip install redis

Python code

40 lines
Python 3.9+
import redis
import json
import time


class DataHelper:
    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_or_set(self, key, data_func, ttl=None):
        cached = self.client.get(key)
        if cached is not None:
            return json.loads(cached)

        fresh_data = data_func()
        ttl = ttl or self.default_ttl
        self.client.setex(key, ttl, json.dumps(fresh_data))
        return fresh_data

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


if __name__ == "__main__":
    helper = DataHelper(default_ttl=5)

    def expensive_data():
        return {"timestamp": time.time(), "items": [1, 2, 3]}

    first = helper.get_or_set("demo:data", expensive_data)
    print(f"First call: {first}")

    second = helper.get_or_set("demo:data", expensive_data)
    print(f"Second call (cached): {second}")
    print(f"Values equal: {first == second}")

    helper.clear("demo:data")
    third = helper.get_or_set("demo:data", expensive_data)
    print(f"After clear — new value: {third}")

Output

stdout
First call: {'timestamp': 1713123456.78, 'items': [1, 2, 3]}
Second call (cached): {'timestamp': 1713123456.78, 'items': [1, 2, 3]}
Values equal: True
After clear — new value: {'timestamp': 1713123456.99, 'items': [1, 2, 3]}

How it works

The DataHelper class wraps a Redis client with decode_responses=True so cached values are returned as strings, not bytes. get_or_set first checks if the key exists; if it does, it returns the decoded JSON. Otherwise it calls data_func, serializes the result with json.dumps, and stores it with setex using the TTL (default 60 seconds, overridden here to 5). This pattern is a classic cache-aside implementation: check cache, on miss fetch the source and populate the cache. The clear method deletes the key so the next call triggers a fresh computation. Using JSON as the serialization format keeps the cache human-readable and works well for dict/list structures.

Common mistakes

  • Forgetting to set `decode_responses=True` leads to bytes objects and errors when comparing with strings.
  • Not using `setex` and manually setting expiration with `set` + `expire` — `setex` is atomic and simpler.
  • Assuming cached data is always fresh; TTL might be too long for frequently changing data.

Variations

  1. Use `pickle` instead of `json` for complex Python objects, although it's less portable.
  2. Add a `get_or_set` with a callable that accepts extra arguments by using `functools.partial`.

Real-world use cases

  • Caching database query results behind an API endpoint to reduce latency and load.
  • Storing expensive computed or fetched data (e.g., third-party API calls) with a short TTL.
  • Implementing a simple session or config store where keys map to JSON objects.

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.