Skip to main content

Connection Pooling

SqbClient never talks to the database directly — it keeps a pool of physical connections (built on the lightning-pool package) and hands one out whenever you call acquire() or execute().

Configuring the pool

Pass a pool object in ClientConfiguration:

const client = new SqbClient({
dialect: 'postgres',
host: 'localhost',
database: 'mydb',
pool: {
max: 20,
min: 2,
idleTimeoutMillis: 60000,
},
});

SqbClient's constructor reads the following fields off pool and coerces each one to its proper type, substituting the default shown below whenever the field is missing or invalid:

OptionTypeDefaultDescription
acquireMaxRetriesnumber0How many times to retry creating a resource after a failed create() before giving up on an acquire() call.
acquireRetryWaitnumber2000Milliseconds to wait between acquire retries.
acquireTimeoutMillisnumber0Milliseconds to wait for a resource before an acquire() call rejects. 0 means wait indefinitely.
idleTimeoutMillisnumber30000Milliseconds an idle connection can sit in the pool before being destroyed (subject to min/minIdle).
maxnumber10Maximum number of connections the pool will create.
maxQueuenumber1000Maximum number of pending acquire() calls that may be queued once the pool is at max.
minnumber0Minimum number of connections the pool tries to keep open.
minIdlenumber0Minimum number of idle connections the pool tries to keep open.
validationbooleanfalseWhether to call the adapter connection's test() method before handing it out from the pool.
note

lightning-pool itself also supports fifo (queue order) and houseKeepInterval (housekeeper tick interval) options, and defaults validation to true. SqbClient builds a brand-new pool options object from only the nine fields above — it does not forward fifo or houseKeepInterval from your pool config, and it explicitly defaults validation to false rather than inheriting lightning-pool's own default of true. If you set pool.fifo or pool.houseKeepInterval, they are currently silently ignored and the underlying pool falls back to lightning-pool's own defaults for those two (fifo: true, houseKeepInterval: 1000).

Internally, the pool's factory is wired to the adapter you registered:

  • create() calls the adapter's connect(config).
  • destroy() calls the adapter connection's close().
  • reset() calls the adapter connection's reset() (run whenever a connection is returned to the pool).
  • validate() calls the adapter connection's test() (only used when validation: true).

Inspecting the pool

client.pool exposes the raw lightning-pool Pool instance, which is useful for monitoring:

console.log(client.pool.size); // total connections (idle + acquired)
console.log(client.pool.acquired); // connections currently checked out
console.log(client.pool.available); // idle connections
console.log(client.pool.pending); // callers waiting for a connection
console.log(client.pool.state); // PoolState

SqbClient also re-emits some of the pool's lifecycle events on itself: closing, close, terminate and error.

Closing the pool

await client.close();

close(terminateWait?: number) shuts the pool down and destroys every connection in it, returning a promise that resolves once that's done. client.isClosed becomes true once the close completes. Pass terminateWait (milliseconds) to bound how long the pool waits for in-flight acquisitions to finish before forcibly terminating them — client.close(0), as used throughout the test suite, terminates immediately.

Next steps