Architecture
This page explains how fastapi-lazyrouter works under the hood.
The cold-start problem
FastAPI builds an OpenAPI schema for every route at import time. When a route declares Pydantic response models, Pydantic must generate the JSON schema for those models. If your application contains hundreds of nested models, this process can take several seconds.
On serverless platforms such as AWS Lambda the runtime kills the container if it does not respond to health checks within ~10 seconds. A large FastAPI application can therefore fail to cold-start.
Lazy router principle
fastapi-lazyrouter splits the work into two phases:
Declaration phase (import time) – route decorators such as
@router.get(...)are intercepted. The arguments are stored in an internal list instead of being registered on the underlyingAPIRouterimmediately. Because the routes are never added to the router, FastAPI has no models to scan and Pydantic does no work.Mount phase (first request) – the
LazyApiRouterMiddlewareinspects every incoming request. When the request path starts with a lazy router’s prefix, the middleware callsLazyApiRouter._lazy_mount(), which:iterates over the stored route declarations,
calls the real
APIRouter.add_api_routefor each one,calls
app.include_router(self)so that FastAPI finally sees the routes,marks the router as loaded so that the operation happens only once.
Global registry
Every LazyApiRouter instance appends itself to the module-level list _ALL_LAZY_ROUTERS. The middleware loops over this list on each request to find routers whose prefix matches the current path. The registry can be cleared with LazyApiRouter.reset_registry(), which is useful in test suites that create many application instances.
Auto-configuration
autoconfigure() makes the library almost transparent:
It adds
LazyApiRouterMiddlewareto the FastAPI app if it is not already present.It monkey-patches
app.include_routerwith a wrapper that converts plainAPIRouterinstances intoLazyApiRouterinstances before delegating to the original method.
After this patch you can keep using APIRouter in your code and still benefit from lazy loading.
Limitations and trade-offs
First-request latency – the very first request that hits a lazy router pays the cost of schema generation. In practice this is usually acceptable because only the router that is actually used is loaded.
OpenAPI completeness –
/docsand/openapi.jsonforce FastAPI to enumerate all routes. The first request to those endpoints therefore triggers the mount of every lazy router, negating the cold-start benefit for that specific request.Middleware ordering –
LazyApiRouterMiddlewareshould be the outermost middleware so that routing-dependent middlewares (e.g. authentication, CORS) operate on fully-mounted routes.