BeginnerSoftware Engineer

Implement cache-aside with Redis

Add a cache-aside layer to an existing Python function that calls a slow external API or database. You will implement get-on-hit, fetch-and-store-on-miss, TTL-based expiry, and explicit invalidation, then measure cache hit rate and latency across 100 calls with realistic key distribution.

Why this matters

Caching is the most impactful single optimisation for read-heavy systems. Cache-aside gives you full control: your application reads from the cache, fetches on miss, and invalidates when data changes. Getting the TTL wrong in either direction (too short, too long) is the most common caching bug in production; and you will reproduce both failure modes in this exercise.

Before you start

Step-by-step guide

  1. 1

    Set up the Redis connection

    Create a redis.Redis client pointing at localhost:6379. Run client.ping(); it should return True. Write a helper that serialises Python objects to JSON for storage and deserialises on read.

  2. 2

    Implement cache-aside read

    Write a get_cached(key, fetch_fn, ttl=60) function: try client.get(key); if a hit, deserialise and return; if a miss, call fetch_fn(), store the result with client.setex(key, ttl, serialised), and return the result. This is the complete cache-aside pattern in under 10 lines.

  3. 3

    Wrap a slow function

    Apply get_cached to a function that simulates a 100ms call. Call it 10 times with the same key. Measure total elapsed time; the first call should be slow, calls 2-10 should be near-instant. Print hit/miss per call.

  4. 4

    Test TTL expiry

    Set TTL to 2 seconds. Call the function, wait 3 seconds, call again. The second call should be a miss even though you just fetched. This is the most common caching surprise: stale data after TTL expiry. Document the invariant for your team.

  5. 5

    Implement explicit invalidation

    Write an invalidate(key) function that runs client.delete(key). Call it after a simulated write operation. Verify the next read is a miss. The cache and the database are inconsistent between writes and the next TTL expiry unless you invalidate explicitly.

  6. 6

    Measure cache hit rate

    Run 100 calls with a Zipf key distribution: a few keys very frequently, many keys rarely. Print hit rate, average latency per hit, average latency per miss, and overall p95 latency. A well-tuned cache should hit 80%+ on typical read workloads.

Relevant Axiom pages

What to do next

Back to Practice Lab