# FastDepends takes FastAPI's dependency injection out of the HTTP layer

> FastDepends is a small Python library that reuses FastAPI's dependency injection machinery with all of the HTTP logic removed, so the same Depends, Annotated and inject interface works in plain sync or async code, in tests, and in a CLI.

**Lancetnik/FastDepends** — FastDepends - FastAPI Dependency Injection system extracted from FastAPI and cleared of all HTTP logic. Async and sync modes are both supported.

- Repository: https://github.com/Lancetnik/FastDepends
- Website: https://lancetnik.github.io/FastDepends/
- Stars: 519 · Forks: 35
- Language: Python
- License: MIT
- Published: 2026-10-22 · Updated: 2026-10-22 · Language: en
- Canonical page: https://hysenlabs.com/projects/lancetnik-fastdepends

## The same interface, without the framework

FastDepends is described as the FastAPI dependency injection system extracted from FastAPI and cleared of all HTTP logic. The README puts it plainly: this is a small library which provides the ability to use FastAPI interfaces in your own projects or tools, and it is a small change of the original FastAPI sources to provide DI functionality in a pure-Python way.

That origin explains the design better than any feature list. FastAPI's dependency injection is a general mechanism that happens to be applied to HTTP request data, and FastDepends keeps the mechanism and drops the HTTP part. What is left resolves dependencies from function calls, from other dependencies and from wherever you tell it to, and it does so with the same Depends marker, the same Annotated syntax and the same inject decorator that FastAPI users already know.

The stated purpose is to boost applications that are not FastAPI, Flask included, and the second purpose is more ambitious. The project can be a core of your own framework for anything, and the README says it was built for the author's other project, Propan, and for FastStream, where you can see full-featured FastDepends usage.

The dependencies are minimal by design. The core requires anyio and typing-extensions, and pydantic and msgspec are optional extras, so you choose which validation model to plug in. Python 3.10 or newer is required, and the package is classified as Production/Stable and typed.

## The decorator that resolves, casts and validates at once

The usage is short enough that the whole API fits in one screen. The sync form is:

```python
from fast_depends import inject, Depends

def dependency(a: int) -> int:
    return a

@inject
def main(
    a: int,
    b: int,
    c: int = Depends(dependency)
) -> float:
    return a + b + c

assert main("1", 2) == 4.0
```

The async form is the same with async def and an asyncio.run around the call.

The decorator does three jobs at once, and the README lists them: it resolves Depends classes, it casts types according to the Python annotation, and it validates incoming parameters using pydantic. The assertion in the example shows the casting in action, since the string "1" is passed where an int is annotated and the result is a float.

The design decision that matters is that the casting and validation happen in the decorated function's own signature, with no separate request object and no framework middleware in the path. A dependency that is annotated as an int gets an int whether it came from a query string, a message payload or a function argument.

## Sync support without the usual wrappers

The features section draws a line in the ground with FastAPI's own approach, and the line is about sync code.

Synchronous code is fully supported in this package, without any async_to_sync, run_sync, syncify or any other tricks. That is a real difference rather than a detail, because the usual way to call an async function from sync code is to wrap it in one of exactly those helpers, and every project ends up with a small layer of them. FastDepends avoids the problem by having a sync path that is sync all the way down.

The second difference is about return values. FastDepends casts functions' return values as well, and the README says it can be very helpful in building your own tools. So a dependency that returns something the annotation says is an int gets coerced to an int, in the same way the inputs are. For a tool whose whole point is to be a building block, having the casts work in both directions is the useful part.

The dependency set explains what this means in practice. anyio is the only runtime dependency of the core, which is the async compatibility layer that lets the same code work under asyncio and under trio. typing-extensions is there for the newer typing syntax the library uses. Everything heavier is optional.

## Overriding dependencies without monkeypatching

The second feature is dependency overriding, and it is where FastDepends starts to look like a container rather than a decorator.

FastDepends can be used as a lightweight DI container, so you can override basic dependencies at application startup or in tests. The default container is the dependency_provider, which is already declared in the library, and the scope is a context manager:

```python
from typing import Annotated

from fast_depends import Depends, dependency_provider, inject

def abc_func() -> int:
    raise NotImplementedError()

def real_func() -> int:
    return 1

@inject
def func(
    dependency: Annotated[int, Depends(abc_func)]
) -> int:
    return dependency

with dependency_provider.scope(abc_func, real_func):
    assert func() == 1
```

You can also bring your own container. The Provider class is created directly, passed to the decorator with dependency_overrides_provider, and scoped the same way. The README says you can inherit the basic Provider class and define any extra logic you want, which is the extension point for a framework that wants its own override resolution.

The test angle is the practical payoff. Overriding a dependency by scope is cleaner than patching a module attribute, and it does not leak between tests because the scope is a context manager.

## Custom fields, for building a framework on top

The third feature is custom fields, and it exists for the case where you are writing your own tool with a similar architecture, FastAPI or otherwise. Custom fields specify application behaviour, and can be used to add something specific to a function's arguments, such as a BackgroundTask, or to parse incoming objects in a special way.

The implementation is a subclass of CustomField with a use method that receives the keyword arguments and returns them, and the decorator then fills the parameter:

```python
from fast_depends import inject
from fast_depends.library import CustomField

class Header(CustomField):
    def use(self, /, **kwargs: AnyDict) -> AnyDict:
        kwargs = super().use(**kwargs)
        kwargs[self.param_name] = kwargs["headers"][self.param_name]
        return kwargs

@inject
def my_func(header_field: int = Header()):
    return header_field

assert my_func(
    headers={ "header_field": "1" }
) == 1
```

The example is a header field, which is the obvious HTTP-adjacent case, but the mechanism is not limited to HTTP. The custom field pulls a value out of a larger context object, and the inject decorator knows to look there.

For anyone building a framework, this is the piece that decides whether FastDepends can be used as the base. The README is direct that the point of custom fields is to give you the decision about why and how you use these tools.

## Where FastDepends fits, and where FastAPI already covers it

The honest starting point is that FastAPI users do not need this. FastAPI ships the same dependency injection, with the same syntax, and it is the original code this project was extracted from. If your project is an HTTP application built on FastAPI, FastDepends adds a dependency and a layer of indirection for no gain.

The case where it earns its place is the one the README describes, a not-FastAPI application, and the author's own projects, Propan and FastStream, are the worked examples. A message broker consumer, a scheduled job, a CLI tool and a web framework all need dependency injection and none of them has a request to resolve dependencies from.

The second case is a framework author. The combination of the inject decorator, the Provider class for overrides and the CustomField extension point is a coherent set of building blocks, and the README says outright that the project can be a core of your own framework for anything. The FastStream integration in particular suggests it has been pressed into that role rather than only theorised about.

The third is a codebase that wants FastAPI-style dependency declarations without the pydantic-heavy core of FastAPI, since the validation model is an extra here rather than the default.

## The trade-offs and the limits

The first cost is the dependency on the FastAPI lineage. The library is a small change of the original FastAPI sources, which means it tracks FastAPI's behaviour closely, including its opinions. When FastAPI changes how it casts or validates, this either follows or drifts, and since it is a separate package with its own release cadence, the two can disagree.

The second is the empty middle. FastDepends sits between a framework and your application, and it adds a layer where the code has to know which of the two owns a given behaviour. Custom fields are where this shows: a field that pulls from headers only makes sense if something puts headers in the context, and that something is the framework you are using, or the one you are writing.

The third is that the DI container is deliberately lightweight. The Provider class and the scope context manager cover dependency overriding, and that is what the README promises. Anything beyond that, service locators, lifecycle management, scoped singletons in the way a Java or Go container would offer, is not in the feature list.

The fourth is the validation model split. The core has no pydantic, so the casting behaviour depends on the extra you install, and the two extras are not identical in behaviour. If your project already has a validation layer, you have to decide which one owns the casts, or you end up validating twice.

The fifth is smallness in a good sense but also in a literal one. The library is a small change of FastAPI's sources, which means it is a small library. The README says there is no way to make dependency injection easier, and that is a fair summary of a package with three or four public entry points.

## Licence, releases and the state of the project

The project is MIT licensed, with the licence file at the root of the repository and the licence declared in the package metadata along with a MIT classifier. The author is Nikita Pastukhov, and the documentation is published at lancetnik.github.io/FastDepends.

The release history is v3.0.9 from 2026-09-19, v3.0.8 and v3.0.7 both from 2026-03-02, and the last push to the repository was on 2026-10-19 with the repository not archived. The version in the package metadata matches the current release, 3.0.9, and the classifiers cover Python 3.10 through 3.14 with pydantic 1 and pydantic 2 both listed as supported frameworks.

The build uses uv, with uv_build as the build backend and a uv.lock in the repository, and the docs group in the dependency groups pulls the documentation theme and a minify plugin. The repository layout is conventional Python packaging with a fast_depends package directory, tests, docs, scripts and a pyproject.toml.

The package is published on PyPI as fast-depends, and the badges in the README cover the version, the supported Python versions, the download counts and the test coverage.

## Conclusion

FastDepends fits a Python developer who likes the way FastAPI declares dependencies and wants that same interface in a library, a worker, a message consumer or a command line tool, where there is no request to resolve a dependency from. It is the wrong tool if your project is already a FastAPI application, since FastAPI ships the same mechanism, and the wrong tool if you want a general purpose injection container, since the scope here is deliberately narrow. Before you adopt it, check three things: that your Python is 3.10 or newer, which the package requires, whether you want the pydantic extra or the msgspec extra, since the core depends only on anyio and typing-extensions, and that you are comfortable with the dependency graph being resolved by the decorator rather than by your framework, because that is the whole design. The code is MIT licensed, the version is 3.0.9, the last push was on 2026-10-19, and the package is published on PyPI as fast-depends.

## FAQ

### What is FastDepends and how does it relate to FastAPI?

It is the FastAPI dependency injection system extracted from FastAPI and cleared of all HTTP logic, a small change of the original FastAPI sources that provides DI in pure Python. The same Depends, Annotated and inject interface works outside a web framework.

### Does FastDepends work with synchronous code?

Yes, and the README highlights that as one of the two main differences from the native FastAPI DI system. Synchronous code is fully supported without any async_to_sync, run_sync, syncify or other tricks, and the package depends only on anyio and typing-extensions at the core.

### How do I override a dependency in FastDepends?

Use the default dependency_provider, or your own Provider instance passed to the decorator as dependency_overrides_provider, and scope an override with the scope context manager, for example `with dependency_provider.scope(abc_func, real_func):`. You can subclass Provider to add your own logic.

### What are CustomField classes for?

They let you add something specific to a function's arguments, such as a BackgroundTask, or parse incoming objects in a special way, by subclassing CustomField from fast_depends.library and implementing its use method. The README positions them for people writing their own tool or framework.

### How do I install FastDepends and what does it require?

With `pip install fast-depends`. Python 3.10 or newer is required, and the pydantic and msgspec integrations are optional extras, so the core only pulls in anyio and typing-extensions. The current version is 3.0.9 and the code is MIT licensed.

## Sources

- [Lancetnik/FastDepends on GitHub](https://github.com/Lancetnik/FastDepends)
- [License: MIT](https://github.com/Lancetnik/FastDepends/blob/main/LICENSE)
- [Project website](https://lancetnik.github.io/FastDepends/)
- [README](https://github.com/Lancetnik/FastDepends/blob/main/README.md)
- [Releases](https://github.com/Lancetnik/FastDepends/releases)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/lancetnik-fastdepends
