- Replace all catch(err: any) with catch(err: unknown) across 8 source files
- Add errorMessage() and errorCode() helpers for safe error property access
- Type nodemailer transport config as SMTPTransport.Options (was any)
- Type health endpoint databaseStatus (was any)
- Type convert route margin param (was any)
- Change queryWithRetry params from any[] to unknown[]
- Update isTransientError to require Error instances (was accepting plain objects)
- 19 new TDD tests (error-type-safety.test.ts)
- Updated existing tests to use proper Error instances
- 598 tests total, all passing, zero type errors
- Add partial unique index on api_keys(stripe_customer_id) WHERE NOT NULL
- Use INSERT ... ON CONFLICT in createProKey for cross-pod dedup
- Add findKeyByCustomerId() to query DB directly
- Success page checks DB before creating key (survives pod restarts)
- Refresh in-memory cache after UPSERT
- queryWithRetry now uses explicit client checkout; on transient error,
calls client.release(true) to DESTROY the dead connection instead of
returning it to pool. Fresh connections are created on retry.
- connectWithRetry validates connections with SELECT 1 before returning
- Health check destroys bad connections on failure
- Reduced idleTimeoutMillis from 30s to 10s for faster stale connection eviction
- Fixes BUG-075: pool kept reusing dead TCP sockets after PgBouncer pod restart
- Enable TCP keepalive on pg.Pool to detect dead connections
- Add connectionTimeoutMillis (5s) to prevent hanging on stale connections
- Add queryWithRetry() with exponential backoff for transient DB errors
- Add connectWithRetry() for transaction-based operations
- Detect PgBouncer "no available server" and other transient errors
- Health check has 3s timeout and returns 503 on DB failure
- All DB operations in keys, verification, usage use retry logic
Fixes BUG-075: PgBouncer failover causes permanent pod failures
- Replace JSON file storage with PostgreSQL (pg package)
- Add db.ts service for connection pool and schema init
- Rewrite keys.ts, verification.ts, usage.ts for async PostgreSQL
- Update all routes for async function signatures
- Add migration script (scripts/migrate-to-postgres.mjs)
- Update docker-compose.yml with DATABASE_* env vars
- Change SLA from 99.9% to 99.5% in landing page