pgtop

A TUI activity monitor for PostgreSQL — htop for your database. Activity, locks, top queries and replication state in a single terminal pane you can keep open all day.

crates.io v0.2.2 Linux · macOS MIT or Apache-2.0
Get pgtop cargo install pgtop · x86_64 and aarch64

The panes

Four views of one connection

Everything PostgreSQL already knows about what it is doing right now is spread across a handful of system views, and reaching any of them means writing the query again. pgtop keeps all four open at once and refreshes them on their own schedules, so switching from “what is running” to “what is blocking it” is a keystroke rather than another psql session.

  1. Activity. A sortable, filterable list of backends from pg_stat_activity — state, wait event, how long the statement has been running, and the query itself.
  2. Locks. A snapshot of pg_locks with granted and waiting state, and the chain of blocking PIDs that leads back to whoever is actually holding things up.
  3. Top queries. pg_stat_statements aggregates — calls, mean time, total time, rows. The tab has three honest states: loading, unavailable because the extension isn’t installed, or data.
  4. Replication. pg_stat_replication as seen from the primary: client address, state, and lag in bytes at each WAL stage.

Above them the header carries the last sixty seconds of transactions per second, active connections and cache hit ratio as sparklines, so a spike that has already passed is still visible when you look up.

Keys

The keys

Tabs are digits, movement is arrows, and everything destructive is a different shape of key than everything safe.

KeyAction
1 2 3 4switch tabs — activity, locks, top queries, replication
move the selection
Enteropen the details of the selected backend
/filter — substring across user, database and query
s / Scycle the sort column / toggle the direction
gactivity: jump to a pid — type the digits, then Enter
ccancel the running query (pg_cancel_backend)
Kterminate the session (pg_terminate_backend)
Alt + 1…9switch the active connection
Escclose the modal
q / Ctrl + Cquit

The scroll wheel scrolls the active table. Mouse capture is on, so holding while selecting bypasses pgtop and lets the terminal handle text selection — which works in iTerm, Terminal, Alacritty, Kitty and GNOME Terminal.

Actions

Cancelling is opt-in, and it is written down

c cancels the running query and K terminates the whole session. Neither is available unless pgtop was started with --allow-actions, and both put a modal in front of you that wants the word yes typed out rather than a keystroke you could hit by reflex. Every action that goes through is written to an audit log.

A profile can also set read_only = true, which forces actions off even when the flag is present. That exists for the case the flag is meant to protect against in the first place: switching from the local profile to production without thinking about which flags are still on the command line.

Connections

More than one database at a time

pgtop prod staging local opens three sessions in one TUI, switched with and a digit. Each connection keeps its own collectors, its own filter and its own selection, so moving between them doesn’t cost you the row you were looking at.

A database hiccup doesn’t take the interface down with it. The reconnect backs off exponentially from 500 ms to a 30-second ceiling and the title says · connecting #N… while it retries, so a monitor left open overnight is still a monitor in the morning.

Configuration

Profiles in one TOML file

pgtop reads ~/.config/pgtop/config.toml, or the same path under $XDG_CONFIG_HOME. A profile is a name, a DSN and whatever you want to differ about that database; naming it on the command line is then the whole invocation.

Settings are layered, lowest to highest: built-in defaults, then the profile, then DATABASE_URL, then the flags you typed. Themes are dark and light.

default_profile = "local"

[profiles.local]
dsn = "host=localhost user=pgtop password=pgtop port=5433 dbname=pgtop"

[profiles.prod]
dsn = "host=prod-db.example user=monitor dbname=catalog"
# read_only = true forces actions off even with --allow-actions
read_only = true

[ui]
theme = "dark"          # or "light"

[intervals]
activity    = 1
locks       = 1
top_queries = 10
replication = 5
stats       = 1

Requirements

What it asks of your database

  1. A role that can read the statistics views. GRANT pg_read_all_stats is enough — pg_monitor also works on PostgreSQL 10 and newer.
  2. For the top queries tab, the pg_stat_statements extension installed (a superuser action) and GRANT SELECT on it. Without it the tab says so rather than showing an empty table.
  3. For cancel and terminate, a role that is superuser, owns the backend’s session, or has pg_signal_backend. Everything else works on a plain read-only role.

TLS

Managed Postgres — RDS, Cloud SQL, Heroku, Supabase — wants TLS, and pgtop honours all five libpq sslmode values straight from the DSN.

sslmodeBehaviour
disableno TLS
prefertry TLS, fall back to plain — the default
requireTLS forced, no certificate verification
verify-caTLS forced, chain validated against the bundled Mozilla root store; the hostname is not checked
verify-fullas verify-ca, and the hostname must match the DSN host

Custom and self-signed CAs are not supported yet — use sslmode=require to skip verification, or open an issue describing the setup.

Get it

Install

Published on crates.io, with pre-built x86_64 and aarch64 binaries for Linux and macOS on every tag.

pgtop on crates.io

Source and releases on github.com/tauvin/pgtop · questions and bug reports

# from source
cargo install pgtop

# pre-built binary, macOS and Linux
curl --proto '=https' --tlsv1.2 -LsSf \
  https://github.com/tauvin/pgtop/releases/latest/download/pgtop-installer.sh | sh

# Homebrew
brew install tauvin/pgtop/pgtop

# Docker, multi-arch
docker run --rm -it ghcr.io/tauvin/pgtop:latest --dsn 'postgres://...'

# Nix flake
nix run github:tauvin/pgtop -- --dsn 'postgres://...'

Pointing it at something

A DSN on the command line, DATABASE_URL in the environment, or the name of a profile — pgtop prod. Several names open several connections at once.

License

Dual-licensed under Apache-2.0 or MIT, at your option — the usual arrangement in the Rust ecosystem, so it drops into either kind of project without a conversation about licences.