You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Add diagnostics_channel support for query and connection lifecycle events #3619
I'd like to propose adding first-class TracingChannel support to pg and pg-pool, following the pattern established by undici in Node.js core.
TracingChannel is a higher-level API built on top of diagnostics_channel, specifically designed for tracing async operations. It provides structured lifecycle channels (start, end, error, asyncStart, asyncEnd) and handles async context propagation correctly, which was the missing piece that makes existing monkey-patching approaches fragile in real-world async Node.js applications.
Current instrumentation's today use IITM (import-in-the-middle) for ESM and RITM for CJS which has a few fragility concerns in today's ecosystem state, a few issues we have today:
Runtime lock-in: both RITM and IITM rely on Node.js-specific module loader internals (Module._resolveFilename, module.register()). They don't work on Bun or Deno, which implement the Node.js API surface but not the module loader internals.
ESM fragility: IITM is built on Node.js's module customization hooks, which are still evolving and have been a persistent source of breakage in the OTEL JS ecosystem.
Initialization ordering: both require instrumentation to be set up before pg is first require()'d. Get the order wrong and instrumentation silently does nothing, which is very hard to debug in production.
Bundling and Externalization: Users have to ensure their instrumented modules are externalized, which is becoming very difficult to guarantee with more and more frameworks bundling the server-side code into single executables, binaries or deployment files.
If pg emits structured events through TracingChannel, instrumentation libraries become subscribers, not patches. Each tool listens independently with no ordering concern, no clobbering, and no internal API dependency.
Before putting together a concrete proposal and PR, wanted to check: is there appetite for this? Happy to spec out channel names, payload shapes, and Node version compatibility considerations if so.
This is the cool part, providers/users or whoever wants to listen in to those tracing events can do something like this:
constdc=require('node:diagnostics_channel');constqueryChannel=dc.tracingChannel('pg:query');queryChannel.subscribe({start(paylaod){// start spans or logging or whatever},asyncEnd(payload){// end the span or report the result in a log or analytics...},error(err){// handle thrown errors}})
For implementation I can start looking into making a PR and go from there, what do you think?
I think that all looks pretty good. Before you start - do you know what kind of performance overhead this would have? I assume allocating a single object for passing to the tracing chanel isn't a huge deal on each call, but interested in that. I can put more comments on the exact payload shapes here if you want, or I can just wait until there's a PR put up. One thing to note is pg currently supports all lts versions of node, so you might have to conditionally require or no-op stuff if it doesn't existin in older versions of node.
Yea there are a few strategies for addressing those:
haSubscribersproperty we can NO-OP if that's false and follow the regular codepath to avoid introducing overhead if there is no listeners, but generally tracing channels have very minimal idle overhead. It depends on what the listener is doing which in case of APM would be significant but wouldn't be a concern of pg itself I think. WDYT?
We can use process.getBuiltInModuleif available to load in tracing channels, if they don't exist we can no-op. if getBuiltInModule doesn't exist we can also NO-OP since it likely won't have tracing channels either.
I can draft up a PR and we can discuss the payloads and specifics there since I have still to check what's possible there.
Activity
brianc commentedon Mar 2, 2026
Definitely open to this! 👍 making instrumentation libraries not rely on monkey patching sounds wonderful.
logaretm commentedon Mar 2, 2026
Great to hear! this is what I was thinking:
Channels
We could have three
TracingChannelinstances, each providingstart/end/asyncStart/asyncEnd/error:pg:queryClient.prototype.querypgpg:connectionClient.prototype.connectpgpg:pool:connectPool.prototype.connectpg-poolPlus plain channels using
diagnostic_channels.channelfor non-lifecycle events if needed:pg:pool:releasepg:pool:removePayloads
Message payloads can be something like this, I had AI sketch them out but we could add more stuff or remove them if needed:
pg:query
pg:connectionpg:pool:connectInstrumentation Pattern
This is the cool part, providers/users or whoever wants to listen in to those tracing events can do something like this:
For implementation I can start looking into making a PR and go from there, what do you think?
brianc commentedon Mar 4, 2026
I think that all looks pretty good. Before you start - do you know what kind of performance overhead this would have? I assume allocating a single object for passing to the tracing chanel isn't a huge deal on each call, but interested in that. I can put more comments on the exact payload shapes here if you want, or I can just wait until there's a PR put up. One thing to note is pg currently supports all
ltsversions of node, so you might have to conditionally require or no-op stuff if it doesn't existin in older versions of node.logaretm commentedon Mar 4, 2026
Yea there are a few strategies for addressing those:
haSubscribersproperty we can NO-OP if that's false and follow the regular codepath to avoid introducing overhead if there is no listeners, but generally tracing channels have very minimal idle overhead. It depends on what the listener is doing which in case of APM would be significant but wouldn't be a concern ofpgitself I think. WDYT?process.getBuiltInModuleif available to load in tracing channels, if they don't exist we can no-op. ifgetBuiltInModuledoesn't exist we can also NO-OP since it likely won't have tracing channels either.I can draft up a PR and we can discuss the payloads and specifics there since I have still to check what's possible there.
Add diagnostics_channel TracingChannel support to pg and pg-pool
sharon77242 commentedon May 8, 2026
Add diagnostics_channel TracingChannel support to pg and pg-pool
Add diagnostics_channel TracingChannel support to pg and pg-pool
Add diagnostics_channel TracingChannel support to pg and pg-pool