Skip to content

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.session proxy, the async with db() context manager, commit_on_exit, and when each session is created and closed.

    Read

  • Engine Lifecycle


    Who owns the engine (db_url vs custom_engine), when it is disposed, and how to dispose it manually outside an ASGI lifespan.

    Read

  • Concurrent Queries


    multi_sessions, max_concurrent, db.gather() and db.connection() — parallel work without blowing past the connection pool.

    Read

  • 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.

    Read

  • Streaming Responses


    Why streaming bodies need their own session and how to write one safely.

    Read

  • Multiple Databases


    create_middleware_and_session_proxy() for independent apps or databases.

    Read

  • SQLAlchemy Events


    Using before_insert / after_update and friends with async sessions.

    Read

  • Type Hints


    Annotate db with DBSessionMeta for full mypy / IDE support.

    Read

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.