Admin: Postgres Connection Floor
Vetrix keeps a baseline number of Postgres connections open even when the platform is completely idle. This "connection floor" is normal and expected — it is the sum of the connection pools each pooled process holds open plus the session-level advisory-lock connections used for leader election. This page documents how to read the floor, what makes it up, and how to lower it.
Floor math
floor ≈ Σ MinConns(per pooled process) + session-level pg_advisory_lock leaders
Where the per-process term sums min_conns over every pooled process:
| Process | Pool(s) |
|---|---|
vetrix-server |
main API pool |
vetrix-worker |
CI/CD runner pool |
vetrix-runner-controller |
main pool plus a separate leader_elector pool |
vetrix-cli |
short-lived pool while a command runs |
vetrix-migrate |
short-lived pool while migrations apply |
Each pooled process keeps min_conns connections open for the lifetime of the
process, whether or not any work is in flight. That is the first term.
The second term is leader election. Vetrix uses session-level
pg_advisory_lock (via pg_try_advisory_lock(hashtext(...))) at roughly ten
sites for daemon leader election. A session-scoped advisory lock is held on
the connection that took it, so each elected leader pins one connection for as
long as it holds leadership. Those connections sit outside the pools' idle math
and add to the floor.
The two long-running, always-pooled processes (vetrix-server and
vetrix-worker) plus the runner-controller's two pools dominate the floor in a
steady-state deployment. vetrix-cli and vetrix-migrate contribute only while
a command or migration is actively running.
Reading the floor in-product
The supported way to see the live per-process connection counts is the
db.conns_by_application breakdown on the admin health endpoint:
GET /api/v1/admin/health
Authorization: Bearer <admin-jwt>
{
"db": {
"reachable": true,
"total_conns": 12,
"idle_conns": 9,
"max_conns": 25,
"conns_by_application": {
"vetrix-server": 6,
"vetrix-worker": 4,
"vetrix-runner-controller": 2
}
}
}
conns_by_application is a best-effort breakdown keyed by Postgres
application_name. Each pooled process stamps its own application_name on its
connections, so the keys map one-to-one to the processes in the floor-math
table:
vetrix-servervetrix-workervetrix-runner-controllervetrix-clivetrix-migrate
A process that is not currently connected (commonly vetrix-cli and
vetrix-migrate, which are short-lived) simply does not appear in the map.
Tuning levers
If the floor is uncomfortably high relative to your Postgres max_connections,
the levers are, roughly in order of effort:
-
Lower
min_conns. Each pooled process'smin_connsis the floor for that process; lowering it shrinks the steady-state baseline at the cost of more connect/disconnect churn under load.min_connsis independently tunable. -
Use transaction-scoped advisory locks where feasible. A transaction-scoped lock (
pg_advisory_xact_lock) releases at transaction end and does not pin a connection for the duration of leadership, unlike the session-scoped locks used today. Where a leader-election site can tolerate transaction-scoped semantics, switching removes one held connection from the floor. -
Front Postgres with pgbouncer. A connection pooler multiplexes many application-side connections onto a smaller set of server-side connections, decoupling the floor the application holds from the connection count Postgres actually sees. This is the highest-leverage option when you cannot reduce the per-process counts directly.
Making the floor observable from DB logs
The breakdown above is point-in-time. To watch the floor and its churn over time directly from the Postgres server, enable connection logging:
log_connections = on
log_disconnections = on
With these on, every connect/disconnect is written to the Postgres server log
with its application_name, which makes both the baseline count and the churn
visible to operators. (An application_name-keyed scrape of pg_stat_activity
is an equivalent alternative.)
Enabling
log_connections/log_disconnectionsis a production Postgres server-config change, performed by the operator on the database — it is not a Vetrix code or runtime-settings change.
See also
- Admin Dashboard API in admin-docs — full
/admin/healthresponse shape.