FastAPI cookbook · Intermediate
Version a FastAPI API without breaking clients
Introduce breaking changes (renamed fields, new semantics) while existing clients keep working.
Approach
Mount versioned routers (/api/v1, /api/v2) that share services but have separate schemas. Keep v1 working, announce deprecation with Deprecation/Sunset headers and docs, monitor v1 usage per client, and remove it only after the sunset date.
Solution
from fastapi import APIRouter, Response
v1 = APIRouter(prefix="/api/v1", tags=["v1"])
v2 = APIRouter(prefix="/api/v2", tags=["v2"])
class UserOutV1(BaseModel):
id: int
name: str # v1: single name field
class UserOutV2(BaseModel):
id: int
first_name: str
last_name: str
@v1.get("/users/{user_id}", deprecated=True)
async def get_user_v1(user_id: int, db: DB, response: Response) -> UserOutV1:
response.headers["Deprecation"] = "@1767225600" # RFC 9745 (Unix timestamp)
response.headers["Sunset"] = "Wed, 30 Jun 2027 00:00:00 GMT"
response.headers["Link"] = '</docs/migrate-to-v2>; rel="deprecation"'
user = await users.get(db, user_id)
return UserOutV1(id=user.id, name=f"{user.first_name} {user.last_name}")
@v2.get("/users/{user_id}")
async def get_user_v2(user_id: int, db: DB) -> UserOutV2:
return await users.get(db, user_id)
app.include_router(v1)
app.include_router(v2)
Pitfalls
- Versioning for additive changes (new optional fields don't need v2).
- Duplicating business logic per version instead of sharing services.
- Removing old versions without usage data or notice.
Variations
- Header-based versioning (
Accept: application/vnd.acme.v2+json). - Date-based versions like Stripe with per-account pinning.
Further reading: RFC 8594: The Sunset HTTP header
Reference: https://www.rfc-editor.org/rfc/rfc8594
More FastAPI recipes
- Add liveness and readiness endpoints to FastAPI
- Add OpenTelemetry tracing to FastAPI
- Add request IDs and structured logs to FastAPI
- Build a WebSocket chat endpoint in FastAPI
- Cache FastAPI responses in Redis
- Call external APIs with retries and timeouts from FastAPI
- Implement role-based access control in FastAPI
- Isolate tenants in a multi-tenant FastAPI app