Skip to main content

FastAPI Caching Route

PR Checks Coverage Coverage Status Docs PyPI

FastAPI route class for response caching before entering the endpoint handler.

fastapi-caching-route plugs into fastapi.APIRouter, stores complete response payloads in an aiocache backend, and serves cache hits directly from the route handler. It is useful for expensive read endpoints where the cache key can be derived from the request path, query parameters, or a custom key builder.

⚠️ This project is a proof of concept and is not yet recommended for production use!

Features

  • Cache regular FastAPI responses and StreamingResponse bodies.
  • Return X-Cache: MISS for stored responses and X-Cache: HIT for cache hits.
  • Generate ETag headers for cached responses.
  • Return 304 Not Modified for matching If-None-Match requests.
  • Build default cache keys from the route path and declared query parameters.
  • Provide custom key builders for path parameters or application-specific keys.
  • Include selected request headers in default cache keys for negotiated responses.
  • Run explicitly configured dependencies before cache lookup, for example API key checks.
  • Pass namespace and ttl through to the underlying aiocache backend.
  • Manually invalidate cached values through FastAPICache.invalidate_cached().

Installation

uv add fastapi-caching-route
pip install fastapi-caching-route

Install FastAPI and a cache backend that matches your application. For local development or tests, aiocache.SimpleMemoryCache is enough:

uv add fastapi aiocache
pip install fastapi aiocache

Basic Usage

Use CachingRoute as the router route class and decorate endpoints with FastAPICache.

from aiocache import SimpleMemoryCache
from fastapi import APIRouter, FastAPI
from fastapi_caching_route import CachingRoute, FastAPICache


router = APIRouter(route_class=CachingRoute)
cache = FastAPICache(SimpleMemoryCache())


@cache()
@router.get('/')
def cached() -> str:
    return 'Hello, World!'


app = FastAPI()
app.include_router(router)

Start an app with this route and call it twice. The first response is produced by the endpoint and stored in the cache:

X-Cache: MISS

The second response is returned from the cache before the endpoint handler is called:

X-Cache: HIT

Routes decorated with @cache() must be registered on a router that uses CachingRoute. A plain APIRoute ignores the cache configuration.

Cache Keys

By default, the cache key is built from the request path and declared query parameters. Query parameter order is normalized, so these two requests hit the same cache entry when the endpoint declares a and b:

/query?a=a&b=b
/query?b=b&a=a

Use a custom key builder when the cache key should be based on path parameters, headers, user context, or another application-specific value.

from fastapi import Request


def user_key_builder(request: Request) -> str:
    user_id = request.scope['path_params']['user_id']
    return f'user:{user_id}'


@cache(key_builder=user_key_builder, ttl=60, namespace='users')
@router.get('/users/{user_id}')
def get_user(user_id: int) -> dict[str, int]:
    return {'id': user_id}

ttl and namespace are passed to aiocache. When the underlying cache instance also has a namespace, FastAPICache concatenates the root and endpoint namespace by default:

cache = FastAPICache(RedisCache(namespace='api'))


@cache(namespace='users')
@router.get('/users/{user_id}')
def get_user(user_id: int): ...


# Resulting namespace: "api:users"

Pass namespace_policy="replace" to FastAPICache if endpoint namespaces should replace the root namespace instead.

If the response representation depends on request headers, include those headers in the default cache key with vary_headers. The route also returns a matching Vary header:

@cache(vary_headers=['Accept-Language'])
@router.get('/localized')
def localized(request: Request) -> str:
    return request.headers.get('accept-language', 'en')

Responses with Vary: * are not cached.

Dependencies Before Cache Lookup

FastAPI dependencies on the route still run on cache misses. If a dependency must also be resolved before cache lookup, pass it to @cache(dependencies=...). This is mainly useful for security dependencies that should reject unauthorized requests before a cached response can be served.

from fastapi import Depends
from fastapi.security import APIKeyHeader


api_key = Depends(APIKeyHeader(name='X-Key'))


@cache(dependencies=[api_key])
@router.get('/private', dependencies=[api_key])
def private_data() -> str:
    return 'secret'

Keep the dependency on the route as well if it must be enforced for cache misses.

Conditional Requests

Cached responses without an existing ETag get one based on the response body. If the endpoint already sets ETag, that value is preserved. On a cache hit, requests with a matching If-None-Match header return 304 Not Modified with an empty body. If-None-Match supports weak tags, tag lists, and *.

curl http://127.0.0.1:8000/cached -H 'If-None-Match: "..."'

Invalidation

Use the same key builder logic when invalidating cache entries after writes.

from fastapi import Request


def user_cache_key(user_id: int) -> str:
    return f'user:{user_id}'


def user_key_builder(request: Request) -> str:
    return user_cache_key(request.scope['path_params']['user_id'])


@cache(key_builder=user_key_builder)
@router.get('/users/{user_id}')
def get_user(user_id: int): ...


@router.patch('/users/{user_id}')
async def update_user(user_id: int) -> dict[str, int]:
    await cache.invalidate_cached(user_cache_key(user_id))
    return {'id': user_id}

invalidate_cached() returns the number of deleted keys reported by the underlying cache backend.

Examples

The repository contains runnable examples:

  • examples/simple.py: minimal cached route.
  • examples/complex.py: cache hits and misses, auth dependency, ETag handling, streaming response caching, query parameter keys, and non-cacheable responses.
  • examples/invalidate.py: custom key builder and manual invalidation after an update.

Follow the detailed walkthrough in the examples README.

Metadata

Release files for fastapi-caching-route 0.6.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for fastapi-caching-route 0.6.0
File Size Uploaded Provenance Actions
fastapi_caching_route-0.6.0.tar.gz 108.6 kB With provenance Details for fastapi_caching_route-0.6.0.tar.gz

Built distribution (wheel)

Table of built distributions (wheels) for fastapi-caching-route 0.6.0
File Interpreter ABI Platform Actions
fastapi_caching_route-0.6.0-py3-none-any.whl Python 3 none any Details for fastapi_caching_route-0.6.0-py3-none-any.whl

Total release size: 118.9 kB

Release files / fastapi_caching_route-0.6.0.tar.gz

Download URL fastapi_caching_route-0.6.0.tar.gz
Size 108.6 kB
Tags Source
SHA-256 checksum
How to use checksums
94324d165b205481be91967389bc0e939bf6336a64fc934c28701e5e9bd0a377
BLAKE2b-256 checksum
How to use checksums
313074bffbaef36a1605143dc79ab2e39a9867e9d79982827193e5acf1450afe
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.12

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Jul 1, 2026.

Transparency log

Release files / fastapi_caching_route-0.6.0-py3-none-any.whl

Download URL fastapi_caching_route-0.6.0-py3-none-any.whl
Size 10.3 kB
Tags Python 3
SHA-256 checksum
How to use checksums
7154e05a794c999a4276913f117d7e63c3232e59a5f9f075603c735b2e4a311e
BLAKE2b-256 checksum
How to use checksums
5d75e07cf25e92fc2c982a70dd55a8991449ace5ea91db44b6590fbe89155c96
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.12

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Jul 1, 2026.

Transparency log

Security for fastapi-caching-route 0.6.0

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

Full provenance

All 2 files in this release have been uploaded with provenance metadata.

Select from 2 files

Attestation for fastapi_caching_route-0.6.0.tar.gz

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Jul 1, 2026.

Transparency log

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Release history Release notifications | RSS feed

This release

0.6.0 This release

2 release files Full provenance

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page