fastapi-router-lazy
Lazy, on-demand loading of FastAPI routers.
Large FastAPI applications pay for every router at startup: importing the
module, building each route's dependency graph and response model, generating
its OpenAPI schema. fastapi-router-lazy mounts a tiny stub per route and
loads the real router only on the first request matching one of its paths.
The full startup win — unused router modules are never imported — comes from generating the route metadata ahead of time and shipping it, so the app reads that cache at startup instead of importing every module. The default in-process extractor is the simplest wiring, but it imports each module at startup to read its routes: it mounts on demand without deferring the imports. The documentation covers which strategy defers imports.
The core needs nothing but FastAPI and works with plain fastapi.APIRouter.
Install
pip install fastapi-router-lazy
# variant/version-aware extraction:
pip install "fastapi-router-lazy[variants]"
Usage
The examples below use "myapp" as the name of your importable Python
package — the one the extractor walks to find modules named router.py, each
exposing an APIRouter:
myapp/ # <- the package name you pass to route_infos_extractor
├── __init__.py
├── users/
│ └── router.py # exposes `router = APIRouter()`
└── items/
└── router.py
Given that layout, lazy loading is two steps.
1. Generate the route metadata (at build time — imports each module once and
writes routes.json):
from pathlib import Path
from fastapi_router_lazy import route_infos_extractor
route_infos_extractor("myapp", cache=True, cache_file=Path("routes.json"))
2. Run lazily (at runtime — reads the metadata and imports no router module until its first matching request):
from pathlib import Path
from fastapi import FastAPI
from fastapi_router_lazy import (
RouterLoader,
lazy_middleware_factory,
route_infos_extractor,
)
app = FastAPI()
# strict=True: use the prebuilt metadata, never re-import at startup.
extractor = route_infos_extractor(
"myapp", cache=True, cache_file=Path("routes.json"), strict=True
)
loader = RouterLoader(extractor, app)
middleware = lazy_middleware_factory(loader)
app.add_middleware(middleware)
# Register the stubs; real routers load on first matching request.
loader.load(middleware)
The default extractor (route_infos_extractor("myapp"), no cache) is the
simplest wiring, but it imports every module at startup to read its routes — it
mounts on demand without deferring imports. Eager loading, deployment filtering,
and the variant/version-aware extractor ([variants]) are covered in the
documentation.
Limitations
Lazy loading trades some runtime dynamism for startup speed:
- lazily-declared routes are absent from
/openapi.jsonand/docsuntil their first matching request mounts them (mount eagerly if you need a complete schema up front); - no
prefix=is applied atinclude_routertime — bake prefixes into theAPIRouteritself; - a stub and a real route sharing a path are resolved by Starlette match order.
See the Limitations section of the docs for details.
Documentation
Full documentation is available at
toilal.github.io/fastapi-router-lazy.
A preview of the in-development develop branch is published at
toilal.github.io/fastapi-router-lazy/dev/.
Requirements
Python 3.12+ and FastAPI.
License
MIT
CHANGELOG
v0.2.2 (2026-07-25)
Bug Fixes
v0.2.1 (2026-07-20)
Bug Fixes
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-router-lazy 0.2.2
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| fastapi_router_lazy-0.2.2.tar.gz | 151.1 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| fastapi_router_lazy-0.2.2-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 174.2 kB
Release files / fastapi_router_lazy-0.2.2.tar.gz
| Download URL | fastapi_router_lazy-0.2.2.tar.gz |
|---|---|
| Size | 151.1 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
2c25eab582a0eb5bf224441430c2986f94b8d87b9baa3226c0e1578e9d4febb7
|
|
BLAKE2b-256 checksum How to use checksums |
a9f9bcada3b3ab63b9e65e1f46a34c02f4bed9403d16adabd9deb28222675083
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
uv/0.11.32 {"installer":{"name":"uv","version":"0.11.32","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_router_lazy-0.2.2-py3-none-any.whl
| Download URL | fastapi_router_lazy-0.2.2-py3-none-any.whl |
|---|---|
| Size | 23.1 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
a0469bbc3c2f6b6066b7f392de13de1105d2859d3384ea148963635955a54944
|
|
BLAKE2b-256 checksum How to use checksums |
9cb1bdf9819e27c661092188950007030e18d80d628e2093c301a72b6ec49f7a
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
uv/0.11.32 {"installer":{"name":"uv","version":"0.11.32","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}
|