Safely Sharing FastAPI Dependencies Across Multiple Routers

FastAPI’s dependency injection system is powerful, but as your application grows and you modularize your code, it’s common to split your API into multiple routers. A question I often get is: "How can I safely share dependencies (like authentication or database access) across routers without duplicating code or causing unexpected side effects?"

Let’s walk through best practices for sharing dependencies among FastAPI routers, as well as some caveats to avoid.


Why Router-Level Dependencies Matter

Assigning dependencies at the router level allows you to:

  1. Reduce duplication: You don’t need to declare the same dependency on every single endpoint.
  2. Enforce security or shared resources: For example, you can ensure all routes under /admin require certain authentication, or that all endpoints under /v1 share caching or throttling logic.

Defining and Sharing Dependencies

Let’s say you have an authentication dependency:

def get_current_user(token: str = Depends(oauth2_scheme)):
    # ... authentication logic ...
    return user

And two routers, items and orders, that should require authentication on all endpoints.

Set the dependency at router creation:

from fastapi import APIRouter, Depends

items_router = APIRouter(
    prefix="/items",
    tags=["items"],
    dependencies=[Depends(get_current_user)]
)

orders_router = APIRouter(
    prefix="/orders",
    tags=["orders"],
    dependencies=[Depends(get_current_user)]
)

Now, every endpoint included via these routers will require your get_current_user dependency.


Caveats and Best Practices

  • Don’t Repeat Dependency Objects: Use the same dependency object, not a copy. That means always refer to the same function (not a redefined lambda, etc.).

  • Composable Dependencies: If you need both shared (e.g., authentication) and endpoint-specific (e.g., role verification) dependencies, let endpoint dependencies depend-on the router dependency:

    def get_admin_user(user: User = Depends(get_current_user)):
        if not user.is_admin:
            raise HTTPException(...)
        return user
    
  • Custom Dependency Classes: For shared state or configuration, custom classes can encapsulate logic and can be instantiated globally, then used as a dependency.


What About Dependency Caching?

Dependency caching (using Depends(..., use_cache=True), which is the default) ensures that, even if a dependency is listed as a router dependency and again on an endpoint, FastAPI will only call it once per request – no wasted effort or mismatched context.


Summary

To efficiently share dependencies across routers in FastAPI:

  • Declare them as global (module-level) functions or classes.
  • Attach them to routers via the dependencies argument.
  • Let router dependencies provide broad concerns (auth, DB), and supplement per-endpoint as needed.

This organization keeps your code DRY, your logic maintainable, and your APIs scalable as they grow!

Happy coding!

— Fast Eddy

Comments

One response to “Safely Sharing FastAPI Dependencies Across Multiple Routers”

  1. Geneva Avatar
    Geneva

    This is a fantastic and concise guide to one of the most important architectural topics in FastAPI development! As you point out, leveraging router-level dependencies is essential for keeping large codebases DRY and maintainable, especially as projects scale and the number of endpoints explodes.

    One practical tip to add: when working with AI coding agents or code generation tools, clearly defining shared dependencies at the router level (as opposed to endpoint level) helps ensure that generated code is both secure and consistent. Automated agents often struggle with duplicated code or subtle inconsistencies—centralizing dependencies reduces this risk and makes the codebase easier to reason about, both for humans and machines.

    Also, your advice about composable dependencies is spot on. I’ve found that layering dependencies (e.g., authentication at the router, then role validation at the endpoint) is a great pattern for building flexible, secure APIs, especially when integrating with external identity providers or complex authorization logic.

    Lastly, the note on dependency caching is critical for performance and correctness, especially when dependencies perform expensive operations or manage state.

    Thanks for addressing these caveats—it’s details like these that lead to robust, production-ready FastAPI systems!

    — Geneva

Leave a Reply to Geneva Cancel reply

Your email address will not be published. Required fields are marked *