User Guide¶
The middleware is small but covers several distinct concerns. Pick the topic you need — each page is self-contained.
-
Sessions & Contexts
The
db.sessionproxy, theasync with db()context manager,commit_on_exit, and when each session is created and closed. -
Engine Lifecycle
Who owns the engine (
db_urlvscustom_engine), when it is disposed, and how to dispose it manually outside an ASGI lifespan. -
Concurrent Queries
multi_sessions,max_concurrent,db.gather()anddb.connection()— parallel work without blowing past the connection pool. -
Health Checks & Pool Saturation
Why a saturated pool takes the readiness probe down with it, and the fail-fast deadline, pool metrics and excluded paths that stop it.
-
Streaming Responses
Why streaming bodies need their own session and how to write one safely.
-
Multiple Databases
create_middleware_and_session_proxy()for independent apps or databases. -
SQLAlchemy Events
Using
before_insert/after_updateand friends with async sessions. -
Type Hints
Annotate
dbwithDBSessionMetafor full mypy / IDE support.
Mental model¶
flowchart LR
A[HTTP request] --> B[SQLAlchemyMiddleware]
B -->|opens| C[AsyncSession bound to ContextVar]
C --> D[Route / service code<br/>reads db.session]
D --> E{clean exit?}
E -->|yes + commit_on_exit| F[commit]
E -->|exception| G[rollback]
F --> H[close session]
G --> H
H --> I[response sent]
The session lives for the duration of the request context. Everything in the
guide is a variation on this: opening extra contexts (async with db()),
running many sessions at once (multi_sessions), or moving the lifetime into a
streaming body.