Mounting Sub-Applications
A FastAPI app is an ASGI application, and ASGI apps can be nested: app.mount attaches another app under a URL prefix. This is how you split a monolith into independently developed modules, or add a completely different framework (Flask, a static site, a GraphQL endpoint) to the same server.
Mounting a Second FastAPI App
from fastapi import FastAPI
# module: orders_app.py
orders_app = FastAPI()
@orders_app.get("/")
def orders_root():
return {"service": "orders"}
@orders_app.get("/items/{item_id}")
def read_order(item_id: int):
return {"order": item_id}
# main.py
from fastapi import FastAPI
from orders_app import orders_app
app = FastAPI()
app.mount("/orders", orders_app, name="orders")
@app.get("/")
def root():
return {"main": True, "orders": "/orders"}
Now /orders/ and /orders/items/42 are served by the sub-app, with its own routes, middleware, and (if enabled) its own /docs at /orders/docs.
Why Mount?
- Modularity: teams own separate FastAPI apps with separate test suites; the main app just mounts them.
- Isolation: each sub-app can have its own middleware, exception handlers, and OpenAPI settings.
- Deployment: in production you can split the mounts into separate services behind a proxy, or keep them in one process.
Middleware and Exceptions
Middleware added on the main app wraps the mounted app (requests pass through main-app middleware first). Exception handlers defined on the sub-app catch errors raised inside it; handlers on the main app catch everything else.
Mounting Static Content the Same Way
app.mount("/static", StaticFiles(...)) is the same mechanism - StaticFiles is just another ASGI app. The pattern generalizes: anything ASGI can be mounted.
Summary
Use app.mount("/prefix", sub_app, name="...") to nest a FastAPI (or any ASGI) app under a URL prefix. You get independent route namespaces, middleware, and docs per module, with the option to later split modules into separate deployed services without changing client URLs.