Set up PostgreSQL
Verbiqo needs one login role with pg_monitor and no rights on your tables. It refuses superusers. The minimum takes about ten minutes per cluster and no restart.
At a glance
| Supported tasks | Ask about slow queries, locks, replication, vacuum, settings, security and capacity, and explain a slow statement without running it. Questions: Ask PostgreSQL. Every check: PostgreSQL checks. |
|---|---|
| Limitations | Verbiqo never reads a row of your tables. Plans of your statements need PostgreSQL 16 or later and pg_read_all_data (how). A standby answers only for itself: the primary’s writes, blocking and vacuum are not visible from it. |
| Supported versions | PostgreSQL 13 and later. Tested on 16 and 17. Versions 13 to 15 are supported from what the code reads, and have not yet been run in a lab. Some reads need a newer server: WAL statistics need 14, and query plans and I/O statistics need 16. PostgreSQL 10 to 12 connect but report less, and 9.6 and older are not supported. |
| Authentication | A password (the setup example uses scram-sha-256), a client certificate (cert in pg_hba.conf), or peer login over a local socket. A client key may have a passphrase. Secrets are kept in the Keychain or Windows Credential Manager. |
| Minimum permissions | A login role that is not a superuser, granted pg_monitor (a built-in role that reads activity, statistics and settings, with no rights on your tables). Each node also needs a pg_hba.conf line, the server’s list of who may connect from where. Commands: Create the monitoring role and Allow it to connect. |
| Connection test | Extensions… › PostgreSQL › Test Connection, or verbiqo pg test <name>. A good test starts with Connected. and shows the version, primary or standby, sessions in use and the TLS in use. You can test before saving if you type the password. |
| First useful question | The app is slow, what is the database doing? Verbiqo samples active sessions for 10 seconds. It reports blocking with the chain of who waits on whom, and the share of time spent on lock and disk waits. Each problem appears as a finding with its evidence and a suggested fix. |
| Safety controls |
|
| Operational limits | At most 500 rows per read. The model may add up to 6 statements per question, after Verbiqo’s own checks. Up to 10 other databases and 5 other cluster nodes per question. Your organization can set tighter limits: Limits you can add. |
What you need
The names below are the ones Verbiqo uses when you ask What should I enable?
| Item | Gives you | Restart? | |
|---|---|---|---|
| Required | A monitoring role granted pg_monitor, not a superuser (step 1) | Sessions, locks, replication, vacuum, settings | No |
| Required | A pg_hba.conf line on each node (step 2) | The connection | No, a reload |
| Required | The connection saved in Verbiqo (step 3) | Asking questions | No |
| Recommended | pg_stat_statements loaded and created (how) | Slowest and costliest statements, work_mem advice, “did the change help?” | Yes, once |
| Recommended | track_io_timing on (how) | Time spent on disk, per statement | No, a reload |
| Optional | Query plans: PostgreSQL 16 or later, and pg_read_all_data (how) | Plans of slow statements, including slow UPDATE and DELETE | No |
| Optional | hypopg (how) | Testing a suggested index before you build it | No |
| Optional | pgstattuple (how) | Measured bloat instead of an estimate | No |
| Optional | Sequence values readable (how) | IDs about to run out | No |
| Optional | track_activity_query_size of at least 4096 (how) | Whole statements in live samples | Yes |
| Optional | auto_explain (how) | Actual plans of slow statements, from the log | Yes, once |
| Optional | Logging that explains incidents afterwards (how) | What happened earlier, from the log through Splunk | No, a reload |
| Optional | WAL archiving for point-in-time recovery (how) | Whether WAL is archived and when the archiver last failed | Yes, once |
| Optional | A metrics source covering this server (how) | Memory sized for the real machine, disk forecasts, Patroni and backups. Without one, state the machine in the question: 32 GB, 8 cores, SSD | No |
Not sure what a server has? Attach it and ask What should I enable? Verbiqo checks every item above and gives the statements for that server.
1. Create the monitoring role
As a superuser, on the primary (it replicates to the standbys):
CREATE ROLE verbiqo LOGIN PASSWORD 'choose-a-password' CONNECTION LIMIT 5;
GRANT pg_monitor TO verbiqo;
pg_monitor lets it read every session's activity, the statistics views and settings. It grants nothing on your tables. Verbiqo holds at most two connections, so the limit of 5 leaves room.
2. Allow it to connect
Add a line to pg_hba.conf on every node, then reload:
hostssl all verbiqo 10.0.0.0/8 scram-sha-256
SELECT pg_reload_conf();
hostssl accepts encrypted connections only. Use all (or list them) so Verbiqo can switch between databases on the server.
3. Add the connection
Open the form
Extensions… › PostgreSQL.
Fill it in
Name (such as orders), host, port (5432), database, user
verbiqo, password.Choose TLS
Verify full with your CA certificate. Without the CA certificate yet, Require: it encrypts without checking the certificate. Keep Prefer for a lab, because it falls back to no encryption when the server offers none. See TLS.
Test, then save
The test shows the version, primary or standby, sessions and the TLS in use.
Or from a terminal:
verbiqo pg add orders --host db1.example.com --port 5432 --database orders --user verbiqo --password-stdin --ssl-mode verify-full --ssl-ca /etc/ssl/company-ca.pem
verbiqo pg test orders
| Sign-in | Give |
|---|---|
| Password on standard input | --password-stdin (piped in. The default form above) |
| Password in a variable | --password-env VAR, for scripts and CI |
| Local socket, peer login | --host /var/run/postgresql and no password. With no --user, Verbiqo signs in as the operating-system user, which a local … peer line in pg_hba.conf compares against. |
| Client key with a passphrase | --ssl-key-passphrase-env VAR or --ssl-key-passphrase-stdin (one value at a time arrives on stdin, so pair it with --password-env) |
Every verb takes --json. One statement, under the same read-only rules as a question (a read-only transaction, catalog and statistics views only):
verbiqo pg query orders "SELECT datname, numbackends FROM pg_stat_database"
TLS and certificates
| Your server | Choose |
|---|---|
| Certificate from a public or company CA | Verify full, with the CA certificate if it is private. |
| Self-signed certificate, or you do not have the CA certificate yet | Require (or tick Insecure). It encrypts, but does not prove which server answered. |
| Not sure whether the server has TLS | Require. If the test says the server does not offer TLS, ask for it to be turned on. Prefer and Disable connect without encryption then, so keep them for a lab. |
Certificate login (cert in pg_hba.conf) | Add the client certificate and key and leave the password empty. If the key has a passphrase, give it in the form’s passphrase field or with --ssl-key-passphrase-env VAR or --ssl-key-passphrase-stdin. It is kept in the Keychain or Credential Manager and never leaves this computer. |
For a certificate login, the certificate’s common name must be the role name:
hostssl all verbiqo 10.0.0.0/8 cert
Modes and options are explained in Encrypted connections.
4. Turn on what helps
Each item is independent: add the ones your policy allows, in any order. Run the statements as a superuser.
Query statistics (recommended)
pg_stat_statements must be preloaded, which needs one restart. Keep any libraries already listed in shared_preload_libraries:
ALTER SYSTEM SET shared_preload_libraries = 'pg_stat_statements';
-- restart PostgreSQL, then in the database Verbiqo connects to:
CREATE EXTENSION pg_stat_statements;
ALTER SYSTEM SET track_io_timing = on;
SELECT pg_reload_conf();
If USAGE on the schema holding pg_stat_statements was revoked from PUBLIC, grant it back to verbiqo.
Plans of your statements, and index tests
Needs PostgreSQL 16 or later. PostgreSQL checks read permission even to plan a statement, so the role needs pg_read_all_data. Verbiqo still never reads rows from your tables: see What Verbiqo can and cannot do. Grant it only if your policy allows.
GRANT pg_read_all_data TO verbiqo;
CREATE EXTENSION hypopg; -- optional: test a suggested index without building it
Measured bloat
CREATE EXTENSION pgstattuple; -- in the database Verbiqo connects to
IDs running out
In each database and schema. The second line runs as the role that creates the sequences:
GRANT SELECT ON ALL SEQUENCES IN SCHEMA public TO verbiqo;
ALTER DEFAULT PRIVILEGES IN SCHEMA public GRANT SELECT ON SEQUENCES TO verbiqo;
Whole statements in live samples
ALTER SYSTEM SET track_activity_query_size = 4096; -- needs a restart
Actual plans of slow statements
auto_explain writes the plans of slow statements, with real row counts, to the log. Verbiqo reads them through Splunk. Add it to the preloaded libraries (one restart), then:
ALTER SYSTEM SET shared_preload_libraries = 'pg_stat_statements,auto_explain';
-- restart PostgreSQL, then:
ALTER SYSTEM SET auto_explain.log_min_duration = '1s';
ALTER SYSTEM SET auto_explain.log_analyze = on;
ALTER SYSTEM SET auto_explain.log_timing = off;
ALTER SYSTEM SET auto_explain.log_format = 'json';
SELECT pg_reload_conf();
WAL archiving
Point-in-time recovery needs every WAL file archived. Use your backup tool’s command. Its exporter in Prometheus also gives Verbiqo the age of the last backup, which the server itself does not record.
ALTER SYSTEM SET archive_mode = on; -- needs a restart
ALTER SYSTEM SET archive_command = 'pgbackrest --stanza=main archive-push %p';
Permissions at a glance
| Permission | Gives Verbiqo | |
|---|---|---|
| Login role, not a superuser | A connection | Required |
pg_monitor | Sessions, statistics, settings, WAL size, pgstattuple | Required |
pg_hba.conf entry on each node | Connecting to each node and database | Required |
CONNECT on a database | Switching to it. Granted to everyone unless revoked | Where revoked |
SELECT on sequences | IDs about to run out (counters only, no rows) | Optional |
pg_read_all_data | Plans of your statements, hypothetical indexes | Optional |
Never grant write rights. Verbiqo has no use for them, and it refuses a superuser outright.
What Verbiqo can and cannot do on your server
Several independent layers keep Verbiqo read-only. Any one of them alone stops a write.
| Layer | What it does |
|---|---|
| The role | No rights on your tables. A superuser is refused when Verbiqo connects, because it bypasses every permission check. |
| Read-only transactions | Every statement runs inside BEGIN READ ONLY and is rolled back straight after. PostgreSQL itself rejects any write, whatever the role could do. |
| A check before sending | One statement at a time, starting with SELECT, WITH, EXPLAIN, SHOW, TABLE or VALUES. Functions that read the server’s files, reach other hosts (dblink), change the running server (end sessions, reload settings, promote, reset statistics) or sleep are refused. |
| A plan check before running | PostgreSQL plans each statement first. It is refused if it reads anything other than the catalog and statistics views, is estimated to cost too much, or would return more than 50,000 rows. |
| Plans of your statements | Planned with EXPLAIN without ANALYZE, so they never run. EXPLAIN ANALYZE is refused on your tables. For an UPDATE, DELETE or INSERT, Verbiqo plans the SELECT that finds the same rows. The write itself never runs. |
| Short limits | 15 seconds per statement, 2 seconds to wait for a lock, and a session left idle in a transaction is ended after 10 seconds, so Verbiqo never holds back vacuum. At most two connections, named verbiqo in pg_stat_activity. At most 500 rows per result. |
| A record of every statement | Each statement Verbiqo sends, and each one it refuses, is on the access record. |
What leaves your network, to the AI service you chose: names (databases, tables, columns, indexes), measurements, settings and the shape of statements. Values are withheld first:
- values in other sessions’ statements, and quoted values in query plans, are replaced with placeholders.
- the sample values PostgreSQL keeps for planning (
pg_statsmost-common values and histograms) are withheld. - no row of your tables is ever read.
What Verbiqo’s reads do touch: like any query, planning takes the lightest lock on the tables named (for milliseconds), which never blocks reads or writes and gives up after 2 seconds if DDL holds the table. Every change Verbiqo recommends is a statement for you to review and run.
Logging for incident reviews
The statistics views show now. The log shows what happened. Verbiqo reads it through Splunk:
ALTER SYSTEM SET log_min_duration_statement = '1s';
ALTER SYSTEM SET log_lock_waits = on;
ALTER SYSTEM SET log_autovacuum_min_duration = '10s';
ALTER SYSTEM SET log_checkpoints = on;
ALTER SYSTEM SET log_temp_files = '10MB';
ALTER SYSTEM SET log_line_prefix = '%m [%p] %q%u@%d app=%a client=%h ';
SELECT pg_reload_conf();
- jsonlog (
log_destination = 'jsonlog', PostgreSQL 15+) works as well as the prefix above. - Messages in English (
lc_messages): Verbiqo reads PostgreSQL’s own wording. - Any log name. Verbiqo recognises the log by its lines. What it finds: Log findings.
Managed services and clusters
- Amazon RDS, Aurora, Cloud SQL, Azure: the administrator account can grant
pg_monitorandpg_read_all_data. Change settings in the parameter group or flags, with the same names. - Clusters: each node needs the
pg_hba.confline, on the same port as the saved connection. Verbiqo finds the other nodes itself. - Machine and history: a connected Prometheus with node_exporter sizes memory settings for the real machine and gives capacity forecasts.
Security and the record of reads
The security review checks this server’s own security (TLS, pg_hba.conf rules, SCRAM, superusers, a supported version) with the same role, and every statement Verbiqo sends is on the access record.
Next: Ask PostgreSQL.
Common errors
The connection test and the answer say what went wrong. Find the message below, then follow the fix.
| Message or symptom | Likely cause | What to do | Needs an administrator? |
|---|---|---|---|
| … is a superuser, so Verbiqo will not use it. | The connection signs in as a superuser. A superuser bypasses every permission check, so Verbiqo refuses it. | Create a monitoring role that is not a superuser, granted pg_monitor (step 1). Then change the connection’s user. | Yes, to create the role. |
| password authentication failed for user … | The user name or password in the connection is wrong. | Type the password again and press Test Connection. Verbiqo 0.1.25 may add Could not reach… under this message. From 0.1.26 the line under it says The server refused the role or password. | Only if the password must be reset. |
| no pg_hba.conf entry for host … | No pg_hba.conf line lets this role connect from this address. With a hostssl line, the connection must also use TLS. | Add the line on every node and reload (step 2). If the line is hostssl, choose TLS Require or stricter. | Yes, to change pg_hba.conf. |
| Could not reach <host>:<port>/<database>. | The host or port is wrong, or a firewall blocks this computer. Verbiqo gives up after 8 seconds. | Check the host and port (5432 by default) in the connection. From 0.1.26 the line names the cause instead: Nothing is listening on…, … does not resolve, or … did not answer in time. | Only if a firewall must be opened. |
| The server’s certificate is not signed by a CA this computer trusts. | The server uses a certificate from a private certificate authority (CA), or a self-signed one. | Give the connection the CA certificate, or name it once in Settings › Trusted CA. For a self-signed lab server, choose Require. More: Certificate and TLS errors. | Only to get the CA file. |
| pg_stat_statements is not installed, so per-statement timings (the slowest and most frequent queries) cannot be seen. | The pg_stat_statements extension, which records statement timings, is not loaded or not created. | Load it and create it in the database Verbiqo connects to (how). Loading it needs one restart. | Yes. |
| The role is not a member of pg_read_all_stats, so other sessions’ query text shows as <insufficient privilege> … | The role was not granted pg_monitor. | Run GRANT pg_monitor TO verbiqo; (step 1). | Yes. |
| Query plans of application statements are not available: … | The server is older than PostgreSQL 16, or the role lacks pg_read_all_data. | If your policy allows, grant pg_read_all_data on PostgreSQL 16 or later (how). The other checks still work without it. | Yes. |