Skip to main content
FastAPI’s dependency injection system supports advanced patterns that enable powerful architectural designs. This guide explores async dependencies, caching strategies, generator-based dependencies with cleanup, and dependency scopes.

Async Dependencies

FastAPI fully supports asynchronous dependencies, which is essential for I/O-bound operations like database queries or API calls.

Basic Async Dependency

Async dependencies are only resolved when used in async path operations. In sync path operations, they’re executed in a threadpool.

Mixing Async and Sync Dependencies

You can mix async and sync dependencies freely:
Be careful when calling sync dependencies from async code. If a sync dependency performs blocking I/O, it can block the event loop. FastAPI runs sync dependencies in a threadpool to mitigate this.

Dependency Caching

By default, FastAPI caches dependency results within a single request. This prevents expensive operations from running multiple times.

How Caching Works

Cache Keys

Dependencies are cached based on:
  • The dependency callable itself
  • OAuth2 scopes (if using Security)
  • The dependency scope (function or request)
See fastapi/dependencies/models.py:63-71 for the cache key implementation.

Disabling Cache

Disable caching for dependencies that must run every time:
Use use_cache=False for:
  • Random number generators
  • Timestamp functions
  • Any dependency with side effects that must execute every time

Generator Dependencies with Cleanup

Generator dependencies (using yield) enable setup and teardown logic, perfect for managing resources.

Basic Generator Dependency

The code after yield executes after the response is sent, ensuring proper cleanup even if exceptions occur.

Async Generator Dependencies

Exception Handling in Dependencies

Code after yield in dependencies runs after the response is sent. You cannot modify the response in the cleanup code.

Dependency Scopes

Dependencies can have different scopes that control their lifecycle:

Function Scope

Function-scoped dependencies are created and destroyed with each path operation function:
scope="function" is required when using generator dependencies with streaming responses. The dependency remains active until the generator completes.

Request Scope

Request-scoped dependencies (the default for generators) are tied to the request lifecycle:
Request-scoped dependencies cannot depend on function-scoped dependencies. This would violate the lifecycle hierarchy.

Scope Rules

  1. Regular (non-generator) dependencies have no scope
  2. Generator dependencies default to scope="request"
  3. Function-scoped dependencies can only depend on other function-scoped dependencies
  4. Request-scoped dependencies cannot depend on function-scoped dependencies
See fastapi/dependencies/utils.py:315-326 for scope validation.

Advanced Patterns

Class-Based Dependencies

Create reusable dependency classes:

Parameterized Dependencies

Create dependency factories:

Nested Dependencies with Context

Best Practices

Use async for I/O-bound operations: Database queries, API calls, and file operations benefit from async dependencies.
Keep dependencies focused: Each dependency should have a single responsibility. Compose complex dependencies from simpler ones.
Cache expensive operations: Let FastAPI’s caching work for you. Only disable when necessary.
Generator cleanup is guaranteed: Code after yield always executes, even if the path operation raises an exception.
Don’t modify responses in cleanup: The response is already sent before cleanup code runs.

See Also