lifespan - modern approach
Modernfrom contextlib import asynccontextmanager
from fastapi import FastAPI, Request
@asynccontextmanager
async def lifespan(app: FastAPI):
# -- STARTUP ---------------------
app.state.db_pool = await create_db_pool()
app.state.redis = await create_redis()
print("Application ready")
yield # app runs here
# -- SHUTDOWN --------------------
await app.state.db_pool.close()
await app.state.redis.close()
print("Cleanup complete")
app = FastAPI(lifespan=lifespan)
# Access in routes via request.app.state
@app.get("/items")
async def items(request: Request):
db = request.app.state.db_pool
return await db.fetch_all("SELECT * FROM items")Watch out: The deprecated @app.on_event("startup") still works, but lifespan is the modern pattern - it also runs correctly under TestClient when used as a context manager.