2.1 KiB
2.1 KiB
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:
- 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
- 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)
- Add database indexes:
- createdAt indexes for time-range queries (alerts, exposures)
- Composite indexes for common filter combinations
- userId indexes on all user-scoped tables
- Implement query result caching:
- Cache user profile lookups (5 min TTL)
- Cache subscription status (1 min TTL)
- Cache dashboard summary (30 sec TTL)
- Add slow query logging:
- Log queries taking >500ms
- Alert on >1s queries
- 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