python 48 lines · 6 steps

Versioning a FastAPI API with mounted sub-apps

Two response schemas and two routers are wired into separate sub-applications so one endpoint can evolve without breaking older clients.

Explained by highlit
1from fastapi import APIRouter, FastAPI, HTTPException
2from pydantic import BaseModel
3 
4 
5class UserV1(BaseModel):
6 id: int
7 name: str
8 
9 
10class UserV2(BaseModel):
11 id: int
12 first_name: str
13 last_name: str
14 email: str
15 
16 
17v1 = APIRouter()
18v2 = APIRouter()
19 
20_users = {1: {"first_name": "Ada", "last_name": "Lovelace", "email": "ada@example.com"}}
21 
22 
23@v1.get("/users/{user_id}", response_model=UserV1)
24async def get_user_v1(user_id: int):
25 user = _users.get(user_id)
26 if user is None:
27 raise HTTPException(status_code=404, detail="user not found")
28 return UserV1(id=user_id, name=f"{user['first_name']} {user['last_name']}")
29 
30 
31@v2.get("/users/{user_id}", response_model=UserV2)
32async def get_user_v2(user_id: int):
33 user = _users.get(user_id)
34 if user is None:
35 raise HTTPException(status_code=404, detail="user not found")
36 return UserV2(id=user_id, **user)
37 
38 
39app = FastAPI(title="Accounts API")
40 
41v1_app = FastAPI(title="Accounts API v1")
42v1_app.include_router(v1)
43 
44v2_app = FastAPI(title="Accounts API v2")
45v2_app.include_router(v2)
46 
47app.mount("/api/v1", v1_app)
48app.mount("/api/v2", v2_app)
01 / 01
STEP 01

Walkthrough

Space play step click any line
Three takeaways
  1. 1Distinct Pydantic response models let each API version expose exactly the shape its clients expect.
  2. 2Mounting separate FastAPI apps isolates versions with their own docs, routers, and titles under one host.
  3. 3A single backing data store can serve multiple schemas by mapping fields per version at the boundary.

Related explainers

Share this explainer

Here's the card — post it anywhere.

Versioning a FastAPI API with mounted sub-apps — share card
Made with highlit — turn any snippet into a walkthrough like this in about a minute.
Explain your code