Lifespan handlers
FastAPI gives you one place to run code at process start and end: lifespan. It is an async context manager. Anything before yield runs at startup. Anything after yield runs at shutdown. This is where you open database pools, warm caches, and drain in-flight work before the process dies.
import logging
from contextlib import asynccontextmanager
from fastapi import FastAPI
from job_store import job_store
logger = logging.getLogger(__name__)
@asynccontextmanager
async def lifespan(app: FastAPI):
"""Run startup / shutdown hooks. Drain background jobs on shutdown."""
logger.info("app_startup")
yield
logger.info("app_shutdown_begin")
await job_store.drain(timeout=10.0)
logger.info("app_shutdown_complete")
app = FastAPI(lifespan=lifespan)One function covers both sides. The yield is the running phase. The lines after yield run on shutdown, bounded by the drain timeout so a stuck job cannot block the container forever.
Lifespan timeline
Startup, serving, shutdown, each in one place.
Quiz: Quiz
Loading practice…