Skip to main content

fastapi-cache-di

Latest Version MIT License Build Status Codecov semantic-release

Speed up FastAPI startup by caching its dependency-tree introspection.

At startup, FastAPI re-introspects every route's dependency tree with no caching, so dependencies shared across many routes (auth checks, DB handles, role guards …) are parsed from scratch again and again. fastapi-cache-di memoizes that work for the duration of route loading, turning O(routes × tree-depth) into O(routes + unique-deps), then restores FastAPI's originals.

Install

pip install fastapi-cache-di
# or
uv add fastapi-cache-di

Usage

Wrap the code that loads your routes with the context manager:

from fastapi import APIRouter, FastAPI

from fastapi_cache_di import fastapi_deps_cache

app = FastAPI()
users = APIRouter()
orders = APIRouter()
billing = APIRouter()

with fastapi_deps_cache(warm_up=app):
    # Registering routes introspects each dependency tree; caching is active here.
    app.include_router(users)
    app.include_router(orders)
    app.include_router(billing)
# included routes built, originals restored here; cache memory freed

warm_up=app matters from FastAPI 0.137: include_router no longer builds the included routes, FastAPI builds them on the first request through each included router (or the first /openapi.json), after the block has exited and without the cache. warm_up builds them when the block exits normally, while the cache is still active. It has no effect before FastAPI 0.137.2, and does not cover routes added after the block, mounted sub-applications or frontend() routes.

Manual patch/unpatch, sharing and inspecting the cache, and the cache-key details are covered in the documentation.

Calling loop-safe dependencies inline

At request time, FastAPI calls every dependency that is neither a coroutine nor a generator through the threadpool: every Depends(SomeClass) and every plain def dependency costs a round trip to a worker thread, often far more than a class whose __init__ only stores its arguments.

patch_fastapi_run_in_threadpool() lets such dependencies run directly on the event loop. It is opt-in, because the library cannot tell whether a call blocks:

  • loop_safe marks one sync function or class (it returns the same object, so Depends(...) and dependency_overrides keep working);
  • inline_classes=True treats every class as loop-safe;
  • everything else still goes through the threadpool, as do sync generator dependencies and sync endpoints.
from typing import Annotated

from fastapi import Depends, FastAPI

from fastapi_cache_di import loop_safe, patch_fastapi_run_in_threadpool

patch_fastapi_run_in_threadpool(inline_classes=True)


@loop_safe
def get_tenant_id() -> str:
    return "acme"


class UserRepository:
    def __init__(self, tenant_id: Annotated[str, Depends(get_tenant_id)]) -> None:
        self.tenant_id = tenant_id


app = FastAPI()


@app.get("/users")
async def list_users(repo: Annotated[UserRepository, Depends()]) -> str:
    return repo.tenant_id

A loop-safe callable must never block: no I/O, no lock, no heavy computation. A blocking call on the event loop stalls every in-flight request. See the documentation for overrides and the marker shared with fastapi-standalone-di.

Skipping the sub-tree of cached dependencies

At request time, FastAPI solves the whole sub-tree of a dependency before checking whether its value is already in the request's cache, so a dependency shared across a deep tree is solved again at every occurrence. patch_fastapi_solve_dependencies() stops that walk as soon as the value is cached. It is opt-in and stays active for the app's lifetime:

from fastapi import FastAPI

from fastapi_cache_di import patch_fastapi_solve_dependencies

patch_fastapi_solve_dependencies()

app = FastAPI()

The values injected into endpoints are unchanged; see the documentation for the details.

Solving routes from a precompiled plan

Even with the sub-tree skip, FastAPI still walks the dependency tree recursively at every request, and recomputes for each dependency what only depends on the route: its cache key, the kind of its callable, the request parameters it reads. patch_fastapi_resolution_plan() compiles each route's dependency tree once, at the route's first request, into a flat plan in FastAPI's evaluation order, then solves every request of that route from the plan in a single loop. It is opt-in and stays active for the app's lifetime:

from fastapi import FastAPI

from fastapi_cache_di import patch_fastapi_resolution_plan

patch_fastapi_resolution_plan()

app = FastAPI()

On a route of 100 dependencies and 211 edges, solving a request takes about a tenth of the time it takes with the sub-tree skip alone. The injected values, the validation errors, the request's dependency cache and the exit order of yield dependencies are the ones FastAPI produces, with dependency_overrides too; see the documentation for the details.

Documentation

Full documentation is available at toilal.github.io/fastapi-cache-di (usage guide, internals, and API reference).

Requirements

  • Python ≥ 3.12
  • FastAPI ≥ 0.112.4

License

MIT © Rémi Alvergnat

CHANGELOG

v0.4.0 (2026-10-20)

Bug Fixes

  • Build included routers' routes under the deps cache with warm_up (#19, 24e5c75)

Features

  • Solve route dependencies from a plan compiled once per route (#20, 913674b)

v0.3.0 (2026-10-16)

Bug Fixes

  • Patch get_flat_dependant only where FastAPI still defines it (#14, 30fbb28)

  • Support FastAPI 0.141+ where get_flat_dependant no longer exists (#14, 30fbb28)

Features

  • Call loop-safe dependencies on the event loop instead of a threadpool hop (#16, a37d214)

  • Skip cached sub-trees when dependency_overrides is set too (#15, bb8a2f7)

  • Skip re-walking the sub-tree of already-cached dependencies at request time (#15, bb8a2f7)

v0.2.1 (2026-07-06)

Bug Fixes

  • Ship py.typed marker for PEP 561 type information (#11, 1a7eb6f)

v0.2.0 (2026-07-05)

Features

v0.1.0 (2026-07-05)

  • Initial Release

Changelog entries are generated automatically by python-semantic-release from Conventional Commits on release.

Metadata

Release files for fastapi-cache-di 0.4.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-cache-di 0.4.0
File Size Uploaded Provenance
fastapi_cache_di-0.4.0.tar.gz 154.4 kB Without provenance Details

Built distribution (wheel)

Table of built distributions (wheels) for fastapi-cache-di 0.4.0
File Interpreter ABI Platform
fastapi_cache_di-0.4.0-py3-none-any.whl Python 3 none any Details

Total release size: 177.8 kB

Release files / fastapi_cache_di-0.4.0.tar.gz

Download URL fastapi_cache_di-0.4.0.tar.gz
Size 154.4 kB
Tags Source
SHA-256 checksum
How to use checksums
6fd697012c5a66b284f3be06412911d6ed816898830f49015a7f83daae2e82a7
BLAKE2b-256 checksum
How to use checksums
bc20edc41f938772c38d955db2eaf3255369aa26a4077e9011cb3059309bb204
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via uv/0.13.3 {"installer":{"name":"uv","version":"0.13.3","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

Release files / fastapi_cache_di-0.4.0-py3-none-any.whl

Download URL fastapi_cache_di-0.4.0-py3-none-any.whl
Size 23.4 kB
Tags Python 3
SHA-256 checksum
How to use checksums
fab64390df51286287bddd52a188b9405b00aa1e9245acec2aec90acfc7c96d5
BLAKE2b-256 checksum
How to use checksums
1077eeab0e175db08c295d39454cc7895e3c484b8ec1b13f6c74087596887bd4
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via uv/0.13.3 {"installer":{"name":"uv","version":"0.13.3","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

Security for fastapi-cache-di 0.4.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.

No provenance found

None of the files in this release were uploaded with provenance metadata.

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.

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