PostgreSQL checks
Every check Verbiqo can run on a PostgreSQL server, grouped by area. You never name a check: you ask in plain words; the model says which areas the question needs, and Verbiqo runs those checks first. Checks that find something serious, such as wraparound or IDs running out, are reported on any question.
How to read this page. Each section is one area. Why it helps says what you get from it. Ask is a question to type that runs it. The table under it lists what Verbiqo checks there: you do not run those one by one. When a check finds a problem, it appears under the answer as a finding, with its evidence and a suggested fix.
How to ask for each area
Attach the server with /pg and the connection’s name, then ask. Any of the words in the middle column brings that area in; a question can bring in several.
| Area | Words Verbiqo goes by without the model | Ask, for example |
|---|---|---|
| Right now | slow, hanging, stuck, blocked, locks, waiting, busy, timeouts, spike, right now, currently, what is it doing, performance | The app is slow, what is the database doing? |
| Queries and indexes | slowest, top queries, expensive, heaviest, missing index, full scans, sequential scans, optimise, cache hit | Which queries cost the most? Are any indexes missing? |
| A statement’s plan | paste the statement into the question: SELECT, UPDATE, DELETE or INSERT | Why is this slow: DELETE FROM … |
| Replication and availability | replication, replica, standby, lag, failover, switchover, primary, WAL, archiving, backups, slots, wraparound, freeze, crash, restart, disk full, recovery, outage | Why is this replica falling behind? |
| PgBouncer | pgbouncer, pooler, pool, waiting for a connection, too many clients, max_client_conn; also read for a problem happening now and for a review | Why are clients waiting for a connection? |
| The whole cluster | cluster, nodes, members, Patroni, leader, standbys | Is the cluster healthy? Who is the leader? |
| Vacuum, bloat and writes | bloat, dead rows, free space, HOT updates, fillfactor, WAL volume, full-page, I/O, writes, background writer, checkpoints, vacuum, reindex | Is anything bloated? Why is WAL growing so fast? |
| Whether a change helped | did the changes help, since the change, before and after, check the tuning, impact of the settings, did the index help, is the new index used | Did the changes help? Is the new index used? |
| Settings and memory | tune, settings, configuration, parameters, memory, shared_buffers, work_mem, autovacuum, checkpoints, max_wal_size, recommendations, best practices | What should I tune on this server? |
| IDs, indexes and statistics | sequences, serial, identity, run out of IDs, duplicate or redundant indexes, stale statistics, analyze, health check | Are any sequences close to running out? |
| Security | security, hardening, audit, superuser, roles, privileges, grants, TLS, SSL, encryption, pg_hba, passwords, SCRAM, MD5, compliance | Security review of this database |
| Capacity | capacity, forecast, how long until, fill up, growth, sizing, scale up, headroom, planning | How long until the disks fill up? |
| What happened | what happened, timeline, incident, outage, yesterday, last night, at 3pm, when did, root cause | What happened on this server last night? |
| Every database on the server | all databases, every database, across the databases | Check all databases for sequences running out |
| The databases and their sizes | database sizes, how big, largest, list the databases, what databases; also read for any question about all databases, space or capacity | Find all databases and their sizes (measured by Verbiqo from pg_database, including databases this connection cannot open) |
| What Verbiqo can see | what should I enable, readiness, permissions, privileges, what does Verbiqo need | What should I enable? |
Right now: sessions, waits and locks
Why it helps: When something is slow or stuck now, it shows what the database is doing and what is holding it up, so you know whether the database is the cause and what to clear.
Ask The app is slow, what is the database doing?
Verbiqo samples the active sessions for 10 seconds (3 to 30, see sampling) and reports:
| Check | What it looks for |
|---|---|
| Blocking | A session blocking others, with the chain of who waits on whom and the statement holding the lock. |
| Lock waits | The share of active session time spent waiting on locks during the sample. |
| Disk waits | The share of active session time spent reading or writing disk. |
| Long-running statement | A session running one statement for a long time. |
| Deadlocks | Deadlocks that happened during the sample. |
| Temporary files | Statements that spilled to temporary files during the sample. |
| Connections near the limit | Client connections as a share of max_connections, with who is using them. |
| Maintenance in progress | Index builds, vacuum, analyze, cluster and base backups running now, with their phase and progress. |
Queries and indexes
Why it helps: Shows which statements cost the most in total and where an index would help, so you fix the few queries that matter most.
Ask Which queries cost the most? Are any indexes missing?
From pg_stat_statements and the table and index statistics. pg_stat_statements covers every database on the server, so each statement names its database and role; one counted once per database and role is shown once, with its figures summed. A statement that runs in another database says so, and is not planned or given an index from the database Verbiqo is connected to: name its database in the question to look at its tables.
| Check | What it looks for |
|---|---|
| One statement dominates | A single statement taking a large share of all statement time. |
| Slow statement | A statement with a high average time per call. |
| Statement spills to disk | A statement writing temporary files on every call: a sort or hash too big for work_mem. |
| Full scans | Large tables read in full many times, which an index would avoid. |
| Unused index | An index never scanned since statistics were reset, with what it costs to keep. An index that backs a unique, primary-key or exclusion constraint is never offered for dropping: where a query does not say, Verbiqo looks it up, and offers no drop when it cannot. Indexes under 1 MB are left out. |
| Invalid index | An index left invalid by a failed CREATE INDEX CONCURRENTLY: maintained on every write, never used. |
| Plans of the heaviest reads | With PostgreSQL 16 and pg_read_all_data, the plans of up to 10 of the heaviest reads (3 if your organization limits how much Verbiqo reads per question), checked as in A statement’s plan. |
| Index for a join | A table a join reads in full for every row of the other side. With hypopg, an index on the join column is tested; it is suggested only if PostgreSQL would use it and it cuts the estimated cost by at least a fifth. |
| Index for sorted results | A query that sorts a whole large table to return its first rows (ORDER BY … LIMIT). With hypopg, an index on the filter’s columns, then the sort columns, is tested, and suggested on the same terms. |
| One index for two queries | The same index suggested for two queries is shown once. Where one query’s index starts with another’s columns, the wider index is tested on both; if PostgreSQL would use it for both, one index is suggested instead of two. |
Index tests use hypothetical indexes: nothing is built, and they are cleared before Verbiqo answers. Without hypopg, only the full-scan suggestions are made, as before.
A statement’s plan
Why it helps: Explains why one statement is slow from its plan, without running it, so you can fix that statement.
Ask Why is this slow? SELECT * FROM orders WHERE status = $1
Paste a statement into the question. Verbiqo asks PostgreSQL for the plan without running it (it needs PostgreSQL 16 and pg_read_all_data, see Explain a slow statement). For an UPDATE, DELETE or INSERT, it plans the search for the rows and reads what writing each row costs.
| Check | What it looks for |
|---|---|
| Full scan that keeps little | A sequential scan of a large table that keeps a small share of its rows: an index candidate. |
| Sort spilled to disk | A sort that did not fit in work_mem. |
| Large sort | A sort the planner expects to be bigger than work_mem. |
| Estimate far from reality | The planner expecting far more or fewer rows than it got, usually stale statistics or correlated columns. |
| Nested loop over a full scan | A table read in full once per outer row. |
| Suggested index tested | With hypopg installed, whether PostgreSQL would use the index Verbiqo suggests, before you build it. |
| Unindexed foreign key (writes) | A DELETE, or an UPDATE of a key, on a table that other tables reference with no index on their side: each row scans the other table. Gives the index to create. |
| Update of an indexed column (writes) | An UPDATE that sets an indexed column cannot be a HOT update, so it writes a new entry in every index of the table. |
| Indexes and triggers (writes) | How many indexes each written row updates, and which triggers run. |
Replication and availability
Why it helps: Shows whether replicas keep up, WAL is archived and IDs are safe from wraparound, so you hear about a failover or data-loss risk before it happens.
Ask Why is this replica falling behind?
| Check | What it looks for |
|---|---|
| WAL archiving failing | The archiver failing, so point-in-time recovery has a gap and WAL piles up. |
| Synchronous standby missing | Commits waiting for a synchronous standby that is not connected. |
| Replay paused | WAL replay paused on a replica. |
| Replay lag | WAL received by a replica but not yet replayed. |
| Vacuum held back | What keeps old rows from being cleaned up: a long session, a prepared transaction, a standby with hot_standby_feedback, or a replication slot. |
| WAL growing | pg_wal holding several times max_wal_size, usually a slot or failing archiving. |
| Freeze overdue | Tables past autovacuum_freeze_max_age. |
| Wraparound | How far each database is towards transaction ID wraparound. Reported on any question once it is close. |
| Logical slot without a consumer | A logical replication slot nobody is reading from, holding WAL on disk; and a consumer far behind the server. |
| Subscriptions | On a server that subscribes: a subscription disabled, enabled without an apply worker, or recording apply and sync errors. |
PgBouncer
Why it helps: Shows whether clients wait in the pooler, and why, so you can tell a pool size problem from a slow database.
Ask Why are clients waiting for a connection?
When the attached address is a PgBouncer, Verbiqo reads its console (the virtual database pgbouncer at the same host, port and credentials; the account must be in stats_users or admin_users). Nothing beyond the attached address is reached; a direct server has no console and the read is skipped.
| Check | What it looks for |
|---|---|
| Clients queued | Clients waiting for a server connection, how long the oldest has waited, and whether the pool is at its size or the server is not answering. |
| Server login stuck | Connections to the server stuck logging in while clients wait. |
| Client limit | Client connections near max_client_conn. |
| Paused or disabled | A database an operator paused or disabled, so clients wait or are refused. |
The whole cluster: standbys, Patroni and backups
Why it helps: Shows every node’s role and state, Patroni’s view and backups, so you know whether the cluster survives losing a node.
Ask Is the cluster healthy? Who is the leader?
From the attached node, Verbiqo reports the others as that node sees them (from a primary, its standbys with their state and lag; from a standby, its upstream). It does not connect to them: a question reaches only what is attached, so another node is read by attaching it in a conversation of its own (see Clusters). If the question itself asks for it, for example read the other nodes with this connection’s credentials, Verbiqo reaches the nodes the attached one reports, at the addresses it gives and with the same credentials; a saved connection is still never used. With a Prometheus source attached in the same conversation it adds Patroni and pgBackRest. A standby it did not read still shows its state, sync mode and replay lag as the primary sees them. A logical replication client (Debezium, a subscriber) is reported as a consumer with its slot and lag, not as a node to attach, and is not counted as a standby.
| Check | What it looks for |
|---|---|
| Node not read | A node that could not be reached or confirmed as part of the cluster, and why. |
| Standby on an old timeline | A standby still on a timeline the primary has left, after a failover. |
| Standby not streaming | A standby that is catching up from archive or has stopped. |
| Patroni member missing | A member Patroni lists that is not replicating from the primary. |
| Patroni leader disagrees | Patroni’s leader is not the node accepting writes. |
| No Patroni leader | The Patroni cluster has no leader. |
| Failovers | Timeline changes in the last 7 days. |
| Restart pending | Patroni reports a restart waiting on this member. |
| Backups | The last pgBackRest backup too old, page checksum errors found by a backup, WAL archiving not recorded, or the stanza reporting an error. |
Vacuum, bloat and writes
Why it helps: Finds wasted space, vacuum falling behind and heavy WAL, so tables stay small and fast and disks do not fill.
Ask Is anything bloated? Why is WAL growing so fast?
| Check | What it looks for |
|---|---|
| Autovacuum behind | Tables with many dead rows and no recent vacuum. |
| Measured bloat | Free space and dead rows in the largest tables, measured with pgstattuple where it is installed. |
| Few HOT updates | Tables where most updates also write every index. When pages are too full, a fillfactor sized from the table: room for the rows updated between vacuums, and at least one more row (70 to 95). When updates change indexed columns, it says fillfactor will not help. |
| Sessions writing buffers | Sessions writing dirty buffers or syncing files themselves, because the background writer and checkpointer fall behind. |
| Background writer limit | The background writer stopping at its per-round limit. |
| Full-page images | A large share of WAL records carrying full page images: checkpoints too close together. |
| WAL buffers full | WAL buffers filling and forcing writes before commit. |
Settings and memory
Why it helps: Judges each setting against what the server actually does, with the statement to change it, so you tune from evidence rather than rules of thumb.
Ask What should I tune on this server?
Settings are judged against what the server has been doing. Sizes that depend on the machine (memory, cores, storage) come from a Prometheus source attached in the same conversation (/prom name), or from what the question states (32 GB of memory, 8 cores, SSD); each finding says which. To see whether a change helped, see After a change.
| Check | What it looks for |
|---|---|
| Unsafe settings | fsync or full_page_writes off (corruption after a crash), autovacuum off. |
| Checkpoints | Checkpoints forced by WAL volume rather than time (raise max_wal_size), or written in a shorter burst than needed (checkpoint_completion_target). On a busy server with a day of statistics, checkpoints every five minutes (checkpoint_timeout). |
| WAL compression | Full-page images making up a large share of WAL while wal_compression is off (PostgreSQL 14+). |
| JIT | Short statements spending a large share of their time compiling (jit, jit_above_cost; PostgreSQL 15+). |
| work_mem | Statements by a role spilling to disk on every call, with the size that would hold them. |
| Temporary files | How much the database writes to temporary files, per day. |
| Autovacuum per table | Large tables waiting for too many dead rows before autovacuum starts. The table’s own threshold is sized from its size: about 100,000 dead rows per vacuum, between 0.2% and 5% of the table. |
| Append-only tables | Tables that are only inserted into, with most pages not yet marked all-visible: index-only scans still read the table, and freezing piles up. Gives a smaller autovacuum_vacuum_insert_scale_factor for the table (PostgreSQL 13+). |
| Autovacuum workers | Every worker busy when Verbiqo looked. |
| Autovacuum speed | Many tables past their vacuum threshold at once while vacuum runs at the default cost limit (autovacuum_vacuum_cost_limit). |
| Vacuum memory | A vacuum scanning the same indexes more than once for lack of memory. |
| shared_buffers and effective_cache_size | Left at their defaults, or out of proportion to the machine’s memory. |
| maintenance_work_mem | Out of proportion to the machine’s memory. |
| Planner costs for SSD | random_page_cost and effective_io_concurrency left at the spinning-disk defaults on SSD or network storage. |
| Parallel workers | Worker limits below what a machine with more than eight cores can use. |
| Memory overcommit | work_mem × max_connections larger than the machine. |
| Disk space | A disk on the machine low on free space. |
IDs, indexes and statistics
Why it helps: Finds IDs about to run out, duplicate indexes and stale statistics: problems that build quietly until inserts fail or plans go wrong.
Ask Are any sequences close to running out?
These are read in one database at a time: the one connected to, or the one the question names. When the server has other databases (the default postgres alone does not count), Verbiqo says which it read and which it did not, and an answer may not call the whole server clear (“nothing needs vacuuming”) from one. Ask about all databases to read each.
| Check | What it looks for |
|---|---|
| Sequences running out | A sequence against the column it feeds: a bigint sequence behind an integer key runs out at 2.1 billion. Reported on any question once it is close. |
| Duplicate and overlapping indexes | An index another one already covers. A covered index under 1 MB is left out; an exact duplicate is always reported. |
| Stale statistics | Tables changed well past autovacuum’s analyze threshold and not analyzed for a day. |
| Partitions | A range-partitioned table whose last partition has already ended or ends within two weeks, and rows piling up in a DEFAULT partition. |
Security
Why it helps: Shows who can do too much, what connects unencrypted and what anyone may change, so you close the gaps an audit would find.
Ask Security review of this database
| Check | What it looks for |
|---|---|
| A permission error you paste | Which role lacks which privilege on the object the error names, read from the catalog, with the grant that should fix it. Verbiqo asks which role when the error does not say (Permission errors). |
| Login superusers | Roles that can log in as superuser. |
| Wide roles | Login roles that can create roles or bypass row security. |
| Expired passwords | Roles whose password has expired. |
| TLS | TLS off, or remote sessions connected without it. |
| Open schemas | Schemas where every role may create objects. |
| pg_hba.conf | Rules that need no password (trust) or send it in clear text (password). Readable only by a superuser; Verbiqo says when it could not check. |
| MD5 passwords | MD5 authentication still in use instead of SCRAM. |
The same checks are controls in the security review, which covers every saved connection at once and maps each to CIS Controls, ISO 27001 and SOC 2.
What Verbiqo can see
Why it helps: Lists what Verbiqo can and cannot see on this server, with the statement that turns each missing item on, so its answers are as complete as possible.
Ask What should I enable?
Ask what should I enable? for each optional extension and setting (pg_stat_statements, pgstattuple, hypopg, track_io_timing and others) marked ready or not, with the statements for your server. The monitoring role itself is in Set up PostgreSQL.
Ready-made reports
A report is one fixed reading of one area: no question, no model, the same output every time. Use one to look at an area yourself, or to share what it shows.
From a terminal, it prints the report:
verbiqo pg run orders blocking-tree
In verbiqo chat, it loads the report into the conversation so you can ask about it. help lists the reports:
/pg orders blocking-tree
/pg orders help
In the desktop apps, there is no report command: ask in your own words, and Verbiqo reads what the question needs.
| Report | Shows |
|---|---|
blocking-tree | Sessions waiting on a lock, and what holds it. |
long-running | Transactions and queries open longest. |
idle-in-transaction | Sessions holding a transaction open while doing nothing. |
table-bloat | Dead rows and when each table was last vacuumed. |
unused-indexes | Indexes never scanned, and what they cost to keep. |
cache-hit | How much of the working set is served from memory. |
replication | Standbys, and how far behind each one is. |
connections | Where connections are going, and how close to the limit. |
settings-of-note | Settings that most often explain a performance complaint. |
Capacity checks for PostgreSQL are on Capacity checks, and what Verbiqo finds in the PostgreSQL log is on Log findings.