FastAPI + Pydantic + SQLAlchemy
Standard FastAPI stack: Pydantic v2, SQLAlchemy 2.0, dependency injection.
# CLAUDE.md — FastAPI + Pydantic + SQLAlchemy
## Project layout
```
src/myapp/
api/
routers/ # one file per resource
deps.py # shared FastAPI dependencies
core/
config.py # pydantic-settings
security.py
db/
base.py # declarative_base
session.py # engine + sessionmaker
models/ # SQLAlchemy ORM models
schemas/ # Pydantic models for I/O
services/ # business logic
main.py # app = FastAPI(); include_router(...)
```
- Models, schemas, and services have separate files. Don't smush them into one `models.py`.
## Pydantic v2
- Use Pydantic v2. `BaseModel` only — no v1 syntax.
- One schema per direction: `UserCreate`, `UserUpdate`, `UserRead`. Never reuse a "User" schema across all three.
- `model_config = ConfigDict(from_attributes=True)` on read schemas to read from ORM objects.
- Validate at the schema. `@field_validator` for single-field rules; `@model_validator` for cross-field.
## SQLAlchemy 2.0
- Use the `Mapped[...]` typed style. No legacy `Column(...)` declarations.
```python
class User(Base):
__tablename__ = "users"
id: Mapped[int] = mapped_column(primary_key=True)
email: Mapped[str] = mapped_column(unique=True)
```
- Use `select(...)` and the modern execute API. No `session.query(...)`.
- Sessions are scoped to a request via a FastAPI dependency:
```python
def get_db() -> Iterator[Session]:
with SessionLocal() as session:
yield session
```
- Commit at the boundary (the endpoint or service), never inside a repository helper.
## Dependency injection
- FastAPI `Depends` is your DI. Use it for db sessions, auth users, settings, feature flags.
- One `deps.py` per app for cross-cutting deps. Per-router deps stay in the router.
- Don't create dependencies that have side effects (logging a metric is fine; mutating state is not).
## Routers
- One router per resource. `prefix="/users"`, `tags=["users"]`.
- Endpoints are thin: parse → call service → return. No business logic in the route function.
- `response_model=UserRead` on every endpoint that returns data. FastAPI strips fields not in the schema.
## Errors
- Raise `HTTPException` for known failure modes with the right status code.
- Custom exception classes inherit from a base; register handlers via `@app.exception_handler(...)`.
- Don't return error dicts from endpoints. Raise.
## Don't
- Don't share a Session across requests. Use `Depends(get_db)`.
- Don't run schema migrations in app startup. Use Alembic and a separate migration step.
- Don't put SQL queries in routers. Wrap them in a repository or service.
- Don't expose ORM models directly from endpoints. Always go through a `*Read` Pydantic schema.
Other FastAPI templates
FastAPI Async + Postgres
Async-first FastAPI with asyncpg, connection pooling, and migrations.
FastAPI JWT Authentication
JWT auth with refresh tokens, password hashing, and role-based access.
FastAPI Testing (pytest + httpx)
Test FastAPI apps with pytest, httpx AsyncClient, and isolated DB fixtures.
FastAPI Production Deploy
Docker images, uvicorn workers, Kubernetes manifests, observability.