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.

main.py
python
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…