FastAPI Cache 2
fastapi-cache2 is a powerful and flexible library for adding caching capabilities to FastAPI applications. It supports various backend stores including Redis, Memcached, Amazon DynamoDB, and an in-memory option. It seamlessly integrates with FastAPI endpoints and general Python functions, enhancing performance by leveraging HTTP cache headers like ETag and Cache-Control. The current version is 0.2.2, and the project is actively maintained.
Warnings
- breaking The `fastapi-cache2` library, specifically version 0.2.2, has a strict dependency requirement on `redis-py` version `4.6.0`. Upgrading `redis-py` to version `5.x` or higher in your project will cause `fastapi-cache2` to break.
- breaking Versions of `fastapi-cache2` 0.2.2 and later can conflict with libraries like `fastapi-pagination` that also rely heavily on FastAPI's dependency injection. This may lead to `UninitializedConfigurationError` when both libraries are used on the same endpoint.
- gotcha The `@cache` decorator must be placed *after* the FastAPI route decorator (e.g., `@app.get('/')`) to function correctly. Incorrect placement can lead to caching not working as expected or runtime errors.
- gotcha When initializing `RedisBackend`, ensure that the `redis-py` client instance passed to it does *not* have `decode_responses=True` set. Cached data is stored as bytes, and decoding them prematurely by the client will corrupt the cache data.
- gotcha For functions decorated with `@cache` using the default `JsonCoder`, it is highly recommended to provide explicit return type annotations. Without them, especially for Pydantic models or custom dataclasses, the cache might store primitive JSON types instead of the fully structured object, potentially leading to unexpected data shapes on cache hits.
- deprecated Older examples might show `FastAPICache.init()` being called within `app.on_event("startup")`. While still functional on older FastAPI versions, `app.on_event` is deprecated in FastAPI versions 0.95.1 and newer.
Install
-
pip install fastapi-cache2 -
pip install "fastapi-cache2[redis]" -
pip install "fastapi-cache2[memcache]" -
pip install "fastapi-cache2[dynamodb]"
Imports
- FastAPICache
from fastapi_cache import FastAPICache
- RedisBackend
from fastapi_cache.backends.redis import RedisBackend
- cache
from fastapi_cache.decorator import cache
- FastAPICache
from fastapi_cache import FastAPICache
- aioredis
from redis import asyncio as aioredis
Quickstart
import os
from collections.abc import AsyncIterator
from contextlib import asynccontextmanager
from fastapi import FastAPI
from fastapi_cache import FastAPICache
from fastapi_cache.backends.redis import RedisBackend
from fastapi_cache.decorator import cache
from redis import asyncio as aioredis
@asynccontextmanager
async def lifespan(_: FastAPI) -> AsyncIterator[None]:
# Use os.environ.get for production readiness if Redis URL is sensitive
redis_url = os.environ.get("REDIS_URL", "redis://localhost")
redis = aioredis.from_url(redis_url)
FastAPICache.init(RedisBackend(redis), prefix="fastapi-cache")
yield
# Optional: Close redis connection if needed, though lifespan context handles it implicitly usually
await redis.close()
app = FastAPI(lifespan=lifespan)
@app.get("/")
@cache(expire=60)
async def index():
return {"hello": "world"}
@app.get("/items/{item_id}")
@cache(expire=30)
async def read_item(item_id: int):
# Simulate an expensive operation
import asyncio
await asyncio.sleep(2)
return {"item_id": item_id, "data": "expensive_data"}