All skills
Skillintermediate
Async SQLAlchemy
```python from sqlalchemy.ext.asyncio import create_async_engine, AsyncSession, async_sessionmaker from sqlalchemy.orm import DeclarativeBase
Claude Code Knowledge Pack7/10/2026
Overview
Async SQLAlchemy
Engine & Session Setup
from sqlalchemy.ext.asyncio import create_async_engine, AsyncSession, async_sessionmaker
from sqlalchemy.orm import DeclarativeBase
engine = create_async_engine(
settings.DATABASE_URL,
echo=settings.DEBUG,
pool_pre_ping=True,
)
async_session = async_sessionmaker(
engine,
class_=AsyncSession,
expire_on_commit=False,
)
class Base(DeclarativeBase):
pass
Model Definition
from sqlalchemy.orm import Mapped, mapped_column, relationship
from sqlalchemy import String, ForeignKey, DateTime, func
from datetime import datetime
class User(Base):
__tablename__ = "users"
id: Mapped[int] = mapped_column(primary_key=True)
email: Mapped[str] = mapped_column(String(255), unique=True, index=True)
username: Mapped[str] = mapped_column(String(50), unique=True)
hashed_password: Mapped[str] = mapped_column(String(255))
is_active: Mapped[bool] = mapped_column(default=True)
created_at: Mapped[datetime] = mapped_column(DateTime, server_default=func.now())
# Relationships
posts: Mapped[list["Post"]] = relationship(back_populates="author", lazy="selectin")
class Post(Base):
__tablename__ = "posts"
id: Mapped[int] = mapped_column(primary_key=True)
title: Mapped[str] = mapped_column(String(200))
content: Mapped[str]
author_id: Mapped[int] = mapped_column(ForeignKey("users.id"))
author: Mapped["User"] = relationship(back_populates="posts")
Database Dependency
from typing import AsyncGenerator
from fastapi import Depends
async def get_db() -> AsyncGenerator[AsyncSession, None]:
async with async_session() as session:
try:
yield session
await session.commit()
except Exception:
await session.rollback()
raise
# Type alias for injection
DB = Annotated[AsyncSession, Depends(get_db)]
CRUD Operations
from sqlalchemy import select, update, delete
from sqlalchemy.orm import selectinload
async def get_user(db: AsyncSession, user_id: int) -> User | None:
result = await db.execute(select(User).where(User.id == user_id))
return result.scalar_one_or_none()
async def get_user_with_posts(db: AsyncSession, user_id: int) -> User | None:
result = await db.execute(
select(User)
.options(selectinload(User.posts))
.where(User.id == user_id)
)
return result.scalar_one_or_none()
async def get_users(db: AsyncSession, skip: int = 0, limit: int = 100) -> list[User]:
result = await db.execute(select(User).offset(skip).limit(limit))
return list(result.scalars().all())
async def create_user(db: AsyncSession, user_in: UserCreate) -> User:
user = User(**user_in.model_dump())
db.add(user)
await db.flush()
await db.refresh(user)
return user
async def update_user(db: AsyncSession, user_id: int, user_in: UserUpdate) -> User:
await db.execute(
update(User)
.where(User.id == user_id)
.values(**user_in.model_dump(exclude_unset=True))
)
return await get_user(db, user_id)
async def delete_user(db: AsyncSession, user_id: int) -> bool:
result = await db.execute(delete(User).where(User.id == user_id))
return result.rowcount > 0
Lifespan Handler
from contextlib import asynccontextmanager
from fastapi import FastAPI
@asynccontextmanager
async def lifespan(app: FastAPI):
# Startup
async with engine.begin() as conn:
await conn.run_sync(Base.metadata.create_all)
yield
# Shutdown
await engine.dispose()
app = FastAPI(lifespan=lifespan)
Quick Reference
| Operation | Method |
|---|---|
| Select one | result.scalar_one_or_none() |
| Select many | result.scalars().all() |
| Eager load | .options(selectinload(...)) |
| Create | db.add(obj) + await db.flush() |
| Update | update(Model).where(...).values(...) |
| Delete | delete(Model).where(...) |
| Commit | await db.commit() |
| Rollback | await db.rollback() |