Skip to content

2.1.0

Choose a tag to compare

@krylosov-aa krylosov-aa released this 19 May 09:32

Concurrent async polling with connection reuse

The monitoring loop was rewritten to poll all hosts concurrently using libpq's non-blocking API and a single poll() over their sockets. A slow or hung host no longer blocks updates for the other hosts — fast hosts continue refreshing on their own cadence while the slow one waits for its own deadline.

PostgreSQL connections are now kept alive between polling iterations instead of being torn down and re-opened on every cycle. This eliminates the per-iteration TCP + auth handshake and noticeably reduces backend churn on the PostgreSQL side (visible in pg_stat_activity — backends now persist across many iterations rather than appearing and disappearing every sleep_ms).

To bound long-tail behavior:

  • pg_status__query_timeout_ms (new, default 5000) — hard deadline for one poll iteration (connect + send + read). On expiry the connection is closed and the host's failure counter is incremented.
  • pg_status__conn_max_age_ms (new, default 300000 = 5 min) — max age of a reused connection. Older connections are recycled on the next iteration so stale state (intermediate NAT, server-side cleanup, etc.) cannot accumulate.

Worst-case time from healthy to dead is now roughly max_fails × query_timeout_ms.