Knex.js ↔︎ PostgreSQL: Are query-response events deduplicated across pooled connections?
0 reputation · 30 Aug 2020, 23:33 UTC
0 reputation · 30 Aug 2020, 23:33 UTC
Implement a low‑noise alerting system that watches Knex’s query and query-response events to flag genuinely slow queries while avoiding duplicate notifications in concurrent workloads.
Knex’s event system is global per instance, and each physical connection in the default pool emits a query-response event when it completes a query. In high‑concurrency scenarios, the same logical query may trigger multiple events, potentially inflating alert counts. The documentation does not state whether these events are deduplicated or if configuration options exist to suppress duplicates.
It remains unclear if the duplication of query-response events is inherent to Knex’s design or can be mitigated through pool or driver settings. Understanding this behavior is critical before deploying production alerting pipelines.
query-response event per logical query when using the default connection pool, or are multiple events emitted for each physical connection that executes the query?35275 reputation · 31 Aug 2020, 08:44 UTC
No, Knex.js does not deduplicate query-response events across pooled connections. Each logical query executed through the Knex instance triggers exactly one query event and one corresponding query-response event, regardless of which physical connection in the pool is utilized. However, if your application logic sends the same query multiple times concurrently, Knex will emit an event for every single execution. There is no built-in mechanism to suppress "duplicate" events for identical SQL strings sent in separate requests.
Knex.js functions as a query builder and connection manager that wraps the underlying driver (such as pg for PostgreSQL). The event lifecycle is tied to the execution context of a specific request, not the content of the SQL query itself:
query event fires when the request is sent to the driver; the query-response event fires when the driver returns the result for that specific network round-trip.SELECT * FROM users five times concurrently, you will receive five separate response events.Since Knex provides no native deduplication, you must implement a tracking layer in your event listeners to prevent alert fatigue. To flag genuinely slow queries without redundant notifications, use a time-based window or a hash-map of active queries.
query event to store a start timestamp in a Map, keyed by the query's unique ID or a request-specific token.query-response listener, retrieve the start time, calculate the duration, and compare it against your slow-query threshold.To verify this behavior in your specific environment (assuming Knex v2.x or v3.x), run the following test:
const knex = require('knex')({ client: 'pg', connection: { ... }, pool: { min: 2, max: 10 } });
let responseCount = 0;
knex.on('query-response', () => { responseCount++; });
// Execute 3 identical queries concurrently
await Promise.all([
knex.raw('SELECT 1'),
knex.raw('SELECT 1'),
knex.raw('SELECT 1')
]);
console.log(`Expected: 3, Actual: ${responseCount}`);
Diagnostic Detail Needed: Are you attaching listeners to the global Knex instance or directly to the underlying pg pool/client? Listeners attached to the pg pool may exhibit different behavior regarding connection-level events versus request-level events.
Use comments to ask for clarification. Post a solution as an answer.
35,275 reputation · 31 Aug 2020, 02:10 UTC
Knex emits a query and a matching query-response for each *execution* that the instance hands off to the driver. The pool only decides which physical socket a request uses; it never re‑emits the same response on a different socket. Consequently, if you fire the same SQL string five times concurrently you will see five query-response events, one per connection that handled that execution.
The event payload already contains a query object with sql and bindings, which you can hash to dedupe at the listener level. A lightweight pattern is to store a timestamp in a Map keyed by that hash and only emit an alert when the duration exceeds your threshold.