Runbook: database pool
Alerts: HikariPoolNearExhaustion, HikariPoolExhausted, HikariAcquireSlow, PostgresConnectionsHigh, PgBouncerClientsWaiting, JdbcP95High.
Symptoms
Timeouts on one service, health flipping, other services fine. That pattern is a pool or a slow query in one schema, not "Postgres is down". If every service times out together, look at the host and PgBouncer.
Check
- Which service's pool is exhausted.
- Active queries in that schema: a missing index on a new filter, a lock from a long transaction, an inbox worker and the API sharing one small pool.
- PgBouncer waiting clients. If the pooler waits and Postgres is idle, the pooler config is the limit.
- Deploy correlation. A new query shape usually arrives with a release.
Repair
- Kill a single runaway query if you can name it and it is not a migration.
- Scale the pool only after you know the query is legitimate. A larger pool on a saturated database makes it worse.
- Add the index in a Flyway migration in the owning service. Do not
CREATE INDEXby hand on production and forget the migration. - Restart the service if connections are leaked and you cannot find the holder. Then file the leak.
The relay uses its own pool (OUTBOX_HIKARI_MAXIMUM_POOL_SIZE). Do not steal API connections for it.