pgjdbc/pgjdbc GitHub issues and pull requests (mirror)
help / color / mirror / Atom feedFrom: vlsi (@vlsi) <[email protected]>
To: pgjdbc/pgjdbc <[email protected]>
Subject: [pgjdbc/pgjdbc] issue #4082: Startup Deadline Model: Make Connection Establishment More Deadline-Based
Date: Thu, 21 May 2026 07:58:06 +0000
Message-ID: <[email protected]> (raw)
Revisit how pgJDBC enforces startup-phase timeouts so connection establishment behaves more like a real deadline budget and less like a caller-side wait wrapper.
Today `loginTimeout` caps how long the caller waits, but the actual connection work continues in a daemon thread until it eventually succeeds or fails. This is understandable from an implementation standpoint, but it is less than ideal operationally under outages and partial network failures.
## Current behavior
Current implementation is centered in:
- `org.postgresql.Driver`
- `org.postgresql.core.v3.ConnectionFactoryImpl`
Notable behaviors:
- `loginTimeout` is enforced by running the connect attempt in a daemon thread and waiting on a condition variable.
- if the timeout fires, the caller gets `08001` / `Connection attempt timed out.`
- the worker thread keeps running in the background
- multi-host `connectTimeout` is now budgeted across hosts, but other startup phases are not modeled as one single propagated deadline
## Why this is worth revisiting
From an SRE perspective:
- timed-out attempts continuing in the background can amplify resource usage during incidents
- timeout semantics become harder to explain: "caller timed out" is not the same as "network operations stopped"
- operators typically want one answer to "how long can connection establishment take?"
## Goals
- make startup timeout behavior closer to a real end-to-end deadline budget
- reduce abandoned in-flight work after caller-side timeout where feasible
- preserve compatibility where possible
## Candidate directions
### 1. Propagate a single absolute startup deadline internally
Instead of treating startup phases as mostly separate timeout domains, compute a single deadline and derive remaining phase budgets from it during:
- TCP connect
- SSL/GSS upgrade
- TLS / GSS handshake
- startup packet exchange
- authentication
### 2. Ensure worker-side blocking I/O obeys the deadline
Even if the background-thread model stays, the worker should ideally apply shrinking remaining timeouts to its own socket-level operations so timed-out attempts do not continue for much longer than the deadline.
### 3. Abort in-flight socket/stream on login timeout where possible
We cannot safely hard-stop Java threads, but if the connect attempt already owns a socket or stream, explicitly closing it on timeout may break the blocking I/O and let the worker unwind sooner.
### 4. Improve observability
If behavior remains two-layered, add clearer debug/trace hooks for:
- caller timeout fired
- in-flight socket was aborted or not
- worker later succeeded and discarded the connection
- worker later failed after caller had already returned
## Open questions
- Can the timeout owner safely close the worker's active socket without introducing races or cleanup hazards?
- Should `loginTimeout` remain implemented via detached worker, or is there a path toward more direct deadline enforcement?
- If a unified startup timeout property were added in the future, how should it interact with `loginTimeout` and `connectTimeout`?
## Compatibility notes
This likely needs phased work:
- tests / observability first
- internal deadline propagation next
- more aggressive cleanup/abort only with careful compatibility review
reply
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Reply to all the recipients using the --to and --cc options:
reply via email
To: github://pgjdbc/pgjdbc
Cc: [email protected], [email protected]
Subject: Re: [pgjdbc/pgjdbc] issue #4082: Startup Deadline Model: Make Connection Establishment More Deadline-Based
In-Reply-To: <<[email protected]>>
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
This inbox is served by agora; see mirroring instructions
for how to clone and mirror all data and code used for this inbox