# 06. Database Connection Pooling & Query Optimization meta: id: web-production-06 feature: web-production priority: P1 depends_on: [] tags: [performance, database, production] objective: - Optimize database connections and queries for production load deliverables: - Connection pooling configuration - Query performance audit - Index optimization - Slow query logging steps: 1. Configure connection pooling: - If using PostgreSQL: configure PgBouncer or use @libsql/client pooling - Set max connections based on server instances (e.g., 20 per instance) - Add connection timeout and idle timeout settings 2. Audit all Drizzle queries for performance: - Check web/src/server/db/schema/*.ts for missing indexes - Review web/src/server/api/routers/*.ts for N+1 queries - Add pagination to all list endpoints (default 50, max 100) 3. Add database indexes: - createdAt indexes for time-range queries (alerts, exposures) - Composite indexes for common filter combinations - userId indexes on all user-scoped tables 4. Implement query result caching: - Cache user profile lookups (5 min TTL) - Cache subscription status (1 min TTL) - Cache dashboard summary (30 sec TTL) 5. Add slow query logging: - Log queries taking >500ms - Alert on >1s queries 6. Set up database performance monitoring tests: - Unit: Test query execution plans for major endpoints - Load: Run 1000 concurrent dashboard loads, verify <200ms p95 - Integration: Test pagination boundaries acceptance_criteria: - Database connection pool configured with max 20 connections - No N+1 queries in any API endpoint - All list endpoints paginated with cursor or offset - Slow query logging active - Dashboard load query <100ms p95 - Alert endpoint query <50ms p95 validation: - EXPLAIN ANALYZE on major queries shows index usage - Load test with k6: 1000 concurrent users, p95 < 200ms - Database CPU <50% under normal load notes: - Current schema has some indexes but may need more for production scale - Drizzle ORM doesn't automatically handle connection pooling — configure at driver level - Consider read replicas if dashboard load is heavy