# 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
