DatabaseMeter

PostgreSQL Learn

How to read pg_stat_activity

Read current PostgreSQL session state and wait evidence without collecting query text, and distinguish normal connection behavior from activity that deserves investigation.

What pg_stat_activity means

pg_stat_activity is a dynamic view with one row per PostgreSQL server process. For client backends, it can show the database, role, application label, connection and transaction timestamps, current state, and wait event.

It is a current observation, not cumulative history. A session can change state immediately after your query, and PostgreSQL does not fully synchronize every field in the row.

Inspect session groups without query text

This bounded, read-only summary omits the query, client address, and process identifier. It excludes the inspecting session and groups the remaining connections by safe operational dimensions.

SELECT
  COALESCE(usename, 'unknown') AS role_name,
  COALESCE(NULLIF(application_name, ''), 'unlabeled') AS application_name,
  COALESCE(state, 'unknown') AS state,
  wait_event_type,
  wait_event,
  count(*) AS session_count,
  min(backend_start) AS oldest_connection_start,
  min(xact_start) AS oldest_transaction_start,
  min(CASE WHEN state = 'active' THEN query_start END) AS oldest_active_query_start
FROM pg_stat_activity
WHERE datname = current_database()
  AND pid <> pg_backend_pid()
GROUP BY usename, application_name, state, wait_event_type, wait_event
ORDER BY session_count DESC, role_name, application_name
LIMIT 50;

Interpret state and time columns

Interpretation of common pg_stat_activity fields
FieldWhat it meansInterpretation guardrail
state = activeThe backend is executing a query.Active can be doing work or waiting; inspect wait_event separately.
state = idleThe backend is waiting for a new client command outside a transaction.Idle pooled connections can be normal and are not automatically a leak.
state = idle in transactionA transaction is open but no query is currently executing.It is a risk signal whose age, locks, and application owner need review—not automatically an incident.
xact_startWhen the current transaction began, or null when no transaction is active.Transaction age is different from connection age and query age.
query_startStart time of the active query, or of the last query when the backend is not active.Only use it as active-query age when state is active.
state_changeWhen the backend last changed state.It does not describe every earlier transition.

Read wait events separately from state

state and wait_event are independent. An active backend with a non-null wait event is executing a query but blocked somewhere, while a client wait can simply mean PostgreSQL is waiting for the application to send more work.

Wait-event types identify broad areas such as locks, client communication, I/O, IPC, buffer pins, timeouts, and extension-defined waits. The event supplies evidence about where a backend is paused; it does not identify the root cause by itself.

Safe inspection workflow

  1. Start with grouped counts and timestamps rather than query text or client addresses.
  2. Compare connection count with the configured limit and with an understood application baseline.
  3. Review the oldest active query and transaction ages, then confirm whether scheduled or administrative work explains them.
  4. For waiting active sessions, inspect the wait type before assuming CPU, storage, or locking is responsible.
  5. Repeat observations over time before labeling a transient snapshot as sustained pressure.

Common misleading interpretations

  • Many idle connections do not necessarily mean PostgreSQL is overloaded; pool design and available connection capacity matter.
  • An active session is not necessarily consuming CPU at that moment.
  • A wait event is not automatically an error, and a null wait event does not prove healthy execution.
  • A long-running query or transaction can be intentional maintenance or reporting work.
  • The query field shows the last query for non-active sessions, not a query that is still running.

When DatabaseMeter can help

The PostgreSQL health check returns bounded counts for active, idle, idle-in-transaction, waiting, long-running query, and long-transaction sessions without returning SQL text, process identifiers, or client addresses.

Connected telemetry stores grouped application, role, state, and connection-count observations. That supports comparisons over time while preserving the distinction between a one-time session snapshot and a sustained connection pattern.

Definitions and sources

Provider and PostgreSQL statements last reviewed August 29, 2026. Pricing consoles and invoices remain authoritative.