# ADR-002: Async SQLAlchemy with PostgreSQL ## Status Accepted ## Context We need to choose an ORM and database for the application. The application will handle concurrent requests and potentially long-running operations (git operations, Docker commands). ### Requirements - Support concurrent API requests without blocking - Handle async operations (database queries + subprocess calls) - Type safety and autocompletion - Migration support - Good Python ecosystem support ## Decision We will use **SQLAlchemy 2.0 with async PostgreSQL** via `asyncpg`. ### Implementation 1. **SQLAlchemy 2.0** with `AsyncSession` and declarative models 2. **PostgreSQL** as the primary database 3. **asyncpg** as the async driver 4. **Alembic** for database migrations ## Consequences ### Positive - **Non-blocking I/O**: Database queries don't block the event loop - **Scalability**: Can handle many concurrent connections - **Type safety**: SQLAlchemy 2.0 has excellent type hint support - **Ecosystem**: Large community, extensive documentation - **Flexibility**: Can fall back to sync operations for complex migrations ### Negative - **Complexity**: Async SQLAlchemy has a steeper learning curve - **Debugging**: Harder to debug async code - **Migration limitations**: Some Alembic operations require sync connections - **Connection pool**: Requires careful configuration ### Alternatives Considered **Prisma ORM** - Pros: Modern, type-safe, auto-generated client - Cons: Less mature Python support, custom query language - Rejected due to less mature ecosystem **Tortoise ORM** - Pros: Built for async, Django-like syntax - Cons: Smaller community, fewer features - Rejected in favor of SQLAlchemy's maturity **Sync SQLAlchemy with threading** - Pros: Simpler, well-understood - Cons: Thread overhead, harder to integrate with async code - Rejected in favor of native async support ## Date 2026-05-17 ## Participants - Development Team