Skip to main content
Headgate borrows from caller-owned pools; it never creates one connection per worker or handler. Use this production sizing rule for either SQL backend:
T includes once, step_once, and application transactions kept open while handler code runs. Sum it across workers sharing the pool; do not add two spare slots per worker. The spare slots serve different purposes:
  1. One keeps lease renewal and worker heartbeats moving while callbacks hold transactions.
  2. One carries admission, enqueue, checkpoints, acknowledgements, duties, inspection, and control API calls.
This is a reliability budget. A smaller pool may queue rather than deadlock, but lease renewal can still wait past expiry while all connections are held by long transactions.

Backend accounting

Push wakeups use one dedicated LISTEN connection outside the pool and fan it out to every worker using that store. Poll-only construction has no listener. Share one store when workers share a pool so five workers do not accidentally create five listeners.

Configuration

Monitor pool waiters and wait duration using deadpool_postgres::Pool::status, pgxpool.Pool.Stat, mysql_async::Pool::metrics, or sql.DB.Stats. A cap prevents connection explosion; it does not make a saturated pool healthy.

Transaction callback rule

Inside once or step_once, use the transaction handle supplied to the callback for application writes and transactional enqueueing. Calling a normal store method while the callback retains its transaction asks the same pool for another connection and can deadlock a fully occupied pool.
Use the supplied transaction handle. If nested acquisition is unavoidable, include it explicitly in the connection budget and test it under full concurrency.