Database And Migrations
The database layer is deliberately small: DatabaseResources owns lazy engine and session-factory creation, route dependencies yield async sessions, and Alembic helpers support downstream services without making every service rebuild the same migration glue. This keeps domain code focused on repositories instead of engine lifecycle details.
Mental Model
Main APIs
| API | Location | Purpose |
|---|---|---|
DatabaseResources | db/session.py | Lazy async engine/session factory plus disposal |
session_dependency_factory | db/session.py | Builds a FastAPI dependency from a provided sessionmaker |
initialize_database_helpers | db/session.py | Produces stable helper callables for downstream services |
AlembicMigrationRunner | db/migration_runner.py | Runs Alembic migrations with connection handling |
collect_migration_status | db/alembic_status.py | Produces health-facing migration status |
Example
from spaps_server_quickstart.db import initialize_database_helpers
from spaps_server_quickstart.settings import create_settings_loader
helpers = initialize_database_helpers(create_settings_loader(ServiceSettings))
get_db_session = helpers.get_db_sessionCommon Mistakes
Do not create a new SQLAlchemy engine per request. Use DatabaseResources or helper callables so
pooling and shutdown stay predictable.
- Forgetting that
session_dependencycommits after the handler yields successfully. - Running migrations with an async driver URL instead of the synchronous URL Alembic expects.
- Adding models without making sure model import registration sees them before writes.