Async Routes & Databases
Combine async def routes with SQLAlchemy 2.0 async sessions and asyncpg.
Search across all documentation pages
Combine async def routes with SQLAlchemy 2.0 async sessions and asyncpg.
Quick-reference recipe card - copy-paste ready.
from fastapi import Depends, FastAPI
from sqlalchemy.ext.asyncio import AsyncSession, async_sessionmaker, create_async_engine
from sqlalchemy import text
engine = create_async_engine("postgresql+asyncpg://user:pass@localhost/db", pool_pre_ping=True)
Session = async_sessionmaker(engine, expire_on_commit=False)
app = FastAPI()
async def get_session():
async with Session() as s:
yield s
@app.get("/ping")
async def ping(session: AsyncSession = Depends(get_session)):
await session.execute(text("SELECT 1"))
return {"db": "ok"}When to reach for this:
from sqlalchemy import select
from sqlalchemy.orm import DeclarativeBase, Mapped, mapped_column
from sqlalchemy.ext.asyncio import AsyncSession
from fastapi import Depends, FastAPI
class Base(DeclarativeBase):
pass
class Item(Base):
__tablename__ = "items"
id: Mapped[int] = mapped_column(primary_key=True)
name: Mapped[str] = mapped_column()
# assume Session/get_session from recipe
app = FastAPI()
@app.get("/items")
async def list_items(session: AsyncSession = Depends(get_session)) -> list[dict]:
rows = (await session.execute(select(Item).limit(20))).scalars().all()
return [{"id": r.id, "name": r.name} for r in rows]What this demonstrates:
| Alternative | Use When | Don't Use When |
|---|---|---|
| Alternate framework in this cookbook | Team standard or existing monolith | Greenfield API with different constraints |
| Managed BaaS | CRUD-only MVP | Custom auth, workflows, or compliance needs |
| gRPC | Internal high-performance RPC | Public HTTP clients and browser access |
Use it when the patterns and trade-offs on this page match your API or data boundary.
Skipping validation, timeouts, or explicit error contracts at the HTTP edge.
Use the framework test client, override dependencies, and assert status plus JSON shape.
Yes - examples target Python 3.14 with pinned framework versions from the stack footer.
Validate and serialize at boundaries; keep services working with typed domain objects.
Prefer async routes when I/O dominates; keep CPU work small or offload to workers.
Thin handlers; services own rules; repositories own queries.
Publish OpenAPI or schema docs that match response models in code.
Explicit URL or header versioning with deprecation windows - avoid silent breaks.
Follow the Related links for the next layer of depth in this section.
Authenticate callers, authorize per resource, rate-limit, and never log secrets.
Measure DB and upstream latency before swapping frameworks.
Stack versions: This page was written for Python 3.14.0 (stable 3.14, maintenance 3.13), FastAPI 0.115+, Django 5.2, Flask 3.1, Pydantic 2, PyTorch 2.6+, pandas 2.2+, Polars 1.x, ruff 0.9+, and uv 0.6+.
Reviewed by Chris St. John·Last updated Jul 19, 2026