# Phase 3: PostgreSQL Support - Discussion Log > **Audit trail only.** Do not use as input to planning, research, or execution agents. > Decisions are captured in CONTEXT.md — this log preserves the alternatives considered. **Date:** 2026-03-24 **Phase:** 03-postgresql-support **Areas discussed:** PostgreSQL driver interface, SQL dialect handling, Connection pooling, Docker Compose integration, Testing strategy **Mode:** Auto (all selections made by Claude using recommended defaults) --- ## PostgreSQL Driver Interface | Option | Description | Selected | |--------|-------------|----------| | pgx/v5/stdlib (database/sql adapter) | Matches SQLiteStore's *sql.DB pattern, Store interface unchanged | ✓ | | pgx native interface | More features (COPY, batch), but different API from SQLiteStore | | | lib/pq | Legacy driver, less maintained | | **User's choice:** [auto] pgx/v5/stdlib — recommended for consistency with existing database/sql pattern **Notes:** Keeping both stores on database/sql means identical constructor signatures and no Store interface changes. --- ## SQL Dialect Handling | Option | Description | Selected | |--------|-------------|----------| | Separate SQL per store | Each store has its own raw SQL, no shared templates | ✓ | | Runtime dialect switching | Single store with if/else for dialect differences | | | Query builder (squirrel/goqu) | Abstract SQL differences behind builder API | | **User's choice:** [auto] Separate SQL per store — recommended per project constraint (no ORM/query builder) **Notes:** PROJECT.md explicitly states "No ORM or query builder — raw SQL per store implementation." --- ## Connection Pooling | Option | Description | Selected | |--------|-------------|----------| | Standard pool defaults | MaxOpenConns(25), MaxIdleConns(5), ConnMaxLifetime(5m) | ✓ | | Minimal single-connection | Match SQLite's MaxOpenConns(1) | | | Configurable via env vars | Let users tune pool settings | | **User's choice:** [auto] Standard pool defaults — appropriate for low-traffic self-hosted dashboard **Notes:** PostgreSQL handles concurrent writes natively, so no mutex needed unlike SQLiteStore. --- ## Docker Compose Integration | Option | Description | Selected | |--------|-------------|----------| | Docker Compose profiles | `--profile postgres` activates postgres service | ✓ | | Separate compose file | compose.postgres.yml alongside compose.yml | | | Always include postgres | Postgres service always defined, user enables via DATABASE_URL | | **User's choice:** [auto] Docker Compose profiles — keeps simple deploys unchanged, opt-in for postgres **Notes:** ROADMAP success criterion #4 states "optional postgres service profile." --- ## Testing Strategy | Option | Description | Selected | |--------|-------------|----------| | Build tag `//go:build postgres` | Tests only run when postgres available | ✓ | | Testcontainers (auto-start postgres) | No external dependency needed | | | Mock store for postgres tests | No real postgres needed, but less confidence | | **User's choice:** [auto] Build tag — simplest approach, CI optionally runs with `-tags postgres` **Notes:** Matches existing test pattern where SQLite tests always run. PostgreSQL tests are additive. --- ## Claude's Discretion - Exact PostgreSQL connection pool tuning beyond defaults - RunMigrations split strategy (two functions vs dialect parameter) - Error message formatting for connection failures - Health check endpoint (optional) ## Deferred Ideas None — discussion stayed within phase scope.