Skip to content

feat: Add multihost support for native js driver#3643

Open
maxbronnikov10 wants to merge 1 commit into
brianc:masterfrom
maxbronnikov10:feat/add-multihost-support
Open

feat: Add multihost support for native js driver#3643
maxbronnikov10 wants to merge 1 commit into
brianc:masterfrom
maxbronnikov10:feat/add-multihost-support

Conversation

@maxbronnikov10
Copy link
Copy Markdown
Contributor

@maxbronnikov10 maxbronnikov10 commented Mar 10, 2026

Summary

  • Add host/port array support to Connection.connect() in the pure JS driver, with automatic TCP-level failover to the next host on connection error
  • Add targetSessionAttrs config option to Connection and wire it through Client
  • Intercept protocol events during startup to collect in_hot_standby and default_transaction_read_only from ParameterStatus messages and validate them against targetSessionAttrs before signalling readyForQuery to the caller
  • Fall back to issuing SHOW transaction_read_only; SELECT pg_catalog.pg_is_in_recovery() for older servers that don't advertise those params

Behavior Changes

When host and port are arrays, the driver tries each host in order. TCP-level errors before the first successful connect silently trigger a retry on the next host. With targetSessionAttrs set, hosts that connect successfully but don't match the session requirement are also silently skipped. If the list is exhausted without a match, an error is emitted.

Problem

The pure JS driver previously only accepted a single host and had no targetSessionAttrs support, unlike the native libpq driver. This made it impossible to use driver for high-availability Postgres setups where you want to connect to whichever replica is currently the primary, or explicitly route to a read replica.

The lack of multihost support meant users had to implement their own failover logic outside the driver, or switch to the native bindings just to get this feature.

Related issues

#1470

Copilot AI review requested due to automatic review settings March 10, 2026 18:01
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR adds multihost connection support to the pg native JavaScript driver's Connection class, enabling TCP-level failover across multiple hosts and PostgreSQL target_session_attrs session attribute filtering (e.g., read-write, read-only, primary, standby, prefer-standby).

Changes:

  • Extended Connection.connect() to accept arrays of hosts and ports, with automatic failover to the next host on TCP connection errors
  • Implemented targetSessionAttrs support that checks PostgreSQL backend parameters (in_hot_standby, default_transaction_read_only) after connection, with a fallback to SHOW/SELECT queries when parameters aren't available via ParameterStatus messages
  • Added comprehensive unit tests covering multihost failover, all targetSessionAttrs modes, and the SHOW query fallback mechanism

Reviewed changes

Copilot reviewed 3 out of 4 changed files in this pull request and generated 2 comments.

File Description
packages/pg/lib/connection.js Core multihost and targetSessionAttrs logic in the Connection class, including stream factory support, emit interception for session attribute checking, and the isHostMatchTargetSessionAttrs helper function
packages/pg/lib/client.js Passes targetSessionAttrs config option through to the Connection constructor
packages/pg/test/unit/connection/multihost-tests.js Unit tests for multihost connectivity, all targetSessionAttrs modes, fallback SHOW queries, and edge cases
.gitignore Adds .history directory to gitignore

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread packages/pg/lib/connection.js Outdated
Comment thread packages/pg/lib/connection.js
@maxbronnikov10 maxbronnikov10 force-pushed the feat/add-multihost-support branch from ffce1e3 to 02f5146 Compare March 10, 2026 18:16
@maxbronnikov10
Copy link
Copy Markdown
Contributor Author

@brianc @charmander hello! can u please check this PR

Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 3 out of 4 changed files in this pull request and generated 2 comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread packages/pg/lib/connection.js Outdated
Comment thread packages/pg/lib/client.js Outdated
@maxbronnikov10 maxbronnikov10 force-pushed the feat/add-multihost-support branch 3 times, most recently from 928c27d to 2778d49 Compare March 10, 2026 18:50
@maxbronnikov10 maxbronnikov10 force-pushed the feat/add-multihost-support branch from 2778d49 to ca31ecf Compare March 29, 2026 16:32
@maxbronnikov10 maxbronnikov10 requested a review from Copilot March 30, 2026 17:50
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 6 out of 7 changed files in this pull request and generated 3 comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread packages/pg/lib/connection.js Outdated
Comment thread packages/pg/lib/connection.js Outdated
Comment thread packages/pg/lib/connection.js Outdated
@maxbronnikov10 maxbronnikov10 force-pushed the feat/add-multihost-support branch 3 times, most recently from 1fab7a1 to 3917365 Compare April 1, 2026 11:42
@maxbronnikov10
Copy link
Copy Markdown
Contributor Author

@brianc @charmander hello! can u please check this PR

@maxbronnikov10 maxbronnikov10 force-pushed the feat/add-multihost-support branch from 3917365 to aebfe47 Compare April 3, 2026 10:03
Copy link
Copy Markdown
Collaborator

@charmander charmander left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I’m not sure if/when I’ll get the chance to give this a thorough review, but the changes to Connection look kind of messy. Is there a reason the logic can’t be something that operates on Connections?

Comment thread packages/pg/lib/connection.js
@maxbronnikov10 maxbronnikov10 force-pushed the feat/add-multihost-support branch 2 times, most recently from 7857655 to cb7fb4a Compare April 7, 2026 19:15
@maxbronnikov10 maxbronnikov10 force-pushed the feat/add-multihost-support branch from cb7fb4a to 6471c21 Compare April 12, 2026 03:22
@maxbronnikov10
Copy link
Copy Markdown
Contributor Author

@brianc hello! can u please check this PR

@brianc
Copy link
Copy Markdown
Owner

brianc commented May 11, 2026

can u please check this PR

will do now. sorry for delay 🙏

@charmander
Copy link
Copy Markdown
Collaborator

what exactly looks confusing?

It introduces a bunch of state on Connection to implement a feature that, as far as I’m aware, is a process that logically attempts multiple unrelated Connection instances.

I don't see any point in taking this out of Connection, it looks like we'll have to refine the pg-pool and then the logic will diverge from Connection, which will have to be refined in two places.

Are you thinking of Client?

@brianc
Copy link
Copy Markdown
Owner

brianc commented May 11, 2026

It doesn't look like vibe code which is good! Looks like you put a lot of thought into this which I appreciate. I think I share some of the concerns @charmander has about it being a lot of additional stuff in connection. I'm kinda okay with it though at first glance. I'm pulling down the branch to open it in my editor to kinda "feel it" more. From my perspective what I'd like to see...though I'm really not sure of the feasibility of it...is there any way to have any integration tests for this? Where maybe you try to connect to several hosts, only one of them being valid in the tests? But actually connect to a backend? I would love it if we could have a docker compose setup w/ multiple postgres's that have failover and readonly settings and all that but that's probably a bit out of scope and wouldn't work great w/ local testing (unless one were to run docker for local testing).

@maxbronnikov10
Copy link
Copy Markdown
Contributor Author

maxbronnikov10 commented May 11, 2026

I believe that logic in Client would create a messier situation. Client operates at a higher level (queries, transactions), while the host iteration, temporary event listeners, and targetSessionAttrs checks are all low-level transport concerns. If I tried to hoist that into Client, I'd have to manually detach and reattach EventEmitter listeners between connection attempts, coordinate stream cleanup, and expose protocol-level details that Client really shouldn't need to know about. In my view, that coupling would be more fragile and leaky than keeping the complexity sealed inside Connection, where it's already responsible for managing the transport lifecycle.

On integration tests — I completely agree they'd be valuable, and I'm keen to dig into that. To do it properly we'd need to set up CI with a multi-node environment (something like Patroni with a primary and read replicas), which would take a bit of infrastructure work. I'm absolutely willing to spend time on that, but I'm conscious it could become a significant addition and risk blocking this PR. Would you be comfortable if I tackled that as a follow-up PR, so we don't inflate the scope and complexity here?

@brianc
Copy link
Copy Markdown
Owner

brianc commented May 11, 2026

On integration tests — I completely agree they'd be valuable, and I'm keen to dig into that. To do it properly we'd need to set up CI with a multi-node environment (something like Patroni with a primary and read replicas), which would take a bit of infrastructure work. I'm absolutely willing to spend time on that, but I'm conscious it could become a significant addition and risk blocking this PR. Would you be comfortable if I tackled that as a follow-up PR, so we don't inflate the scope and complexity here?

yeah for sure. there are some tests covering it already, and all existing tests pass which are big first steps. I am still churning through my backlog of PRs and issues today, returning to computer, so I might not get to do a comprehensive dive until tomorrow. If you don't hear back sometime in the afternoon USA time please ping me at brian.m.carlson@gmail.com or get on the discord and ping me directly there. My inbox is an absolute nightmare of github notification emails and things can get lost in the shuffle, but I want to bring this over the finish line one way or another as its pretty big & I don't want to break it w/ merge conflicts.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants