Week 11: Caching & Performance

Build the next production-ready layer of your FastAPI service through clear concepts, a focused implementation and a practical exercise.

Module 8 of 12Week 11 of 15~3-4 HoursHands-on Exercise Included

By the end of this week, you'll be able to

  • Redis cache-aside pattern
  • Safe invalidation and TTLs
  • Query profiling, pools and background tasks

1. Redis cache-aside pattern

Start with the contract: make inputs, outputs and failure behavior explicit before adding infrastructure. This keeps the feature easy to reason about and gives tests a stable boundary.

2. Safe invalidation and TTLs

Apply the pattern through a small vertical slice. Keep framework wiring at the edge and business decisions in focused functions or services that can be tested without starting the whole application.

core example
async def get_task(task_id: int):
    key = f"task:{task_id}"
    if cached := await redis.get(key):
        return TaskOut.model_validate_json(cached)
    task = await repository.get(task_id)
    await redis.set(key, TaskOut.model_validate(task).model_dump_json(), ex=60)
    return task

3. Query profiling, pools and background tasks

Treat failure paths as part of the design. Add bounded resource usage, meaningful errors and a verification step so the behavior remains dependable under real production conditions.

4. Hands-on Exercise

Build the feature

Cache task reads, invalidate on writes, then measure query count and response latency before and after the change.

Definition of done

  • The happy path works through the real HTTP boundary.
  • At least one failure path is handled and tested.
  • Configuration and secrets stay outside source code.
  • The README explains how to run and verify the result.

5. Knowledge Check

Why is cache invalidation usually performed after a successful database commit?

Show answer

Invalidating earlier can expose stale or inconsistent states if the transaction later rolls back.