How-to guide
Create the monitoring role
Elevarq Signals connects to each PostgreSQL target as a single, dedicated login role. This guide creates that role with least-privilege, read-only access — the role can read statistics and settings but cannot modify your data or schema. You run it once per database cluster.
Signals reads statistics only — it never modifies your data or schema. The least-privilege way to grant the read access it needs is the built-in pg_monitor role. This is a one-time setup per cluster. For why the role is read-only and how the daemon enforces that at runtime, see why read-only. For how to supply the resulting credential to Signals, see Authentication methods.
Connect as a superuser or RDS master user
Connect to the database you want to observe as a role that can CREATE ROLE — a superuser on self-managed PostgreSQL, or the master user on a managed service. Run the SQL below once per database cluster.
Create the read-only role
Run the following as a superuser (or the RDS master user), connected to the database you want to observe. The role is created NOSUPERUSER NOCREATEDB NOCREATEROLE NOREPLICATION NOBYPASSRLS so it has no privileges beyond reading monitoring data:
-- Run as a superuser on each target database cluster.
CREATE ROLE signals LOGIN
PASSWORD '<set-via-secret-store>'
NOSUPERUSER
NOCREATEDB
NOCREATEROLE
NOREPLICATION
NOBYPASSRLS;
GRANT pg_monitor TO signals;
-- Allow it to connect to the database you want to observe.
GRANT CONNECT ON DATABASE your_database TO signals;pg_monitor is a built-in PostgreSQL role (since 10) that aggregates the read-only monitoring sub-roles:
pg_read_all_settings— read all GUC values, including those marked as superuser-only.pg_read_all_stats— read allpg_stat_*views regardless of the owning role.pg_stat_scan_tables— execute monitoring functions that may take ACCESS SHARE locks.
This grant is read-only. It does not allow INSERT, UPDATE, DELETE, CREATE, schema changes, replication, or row-security bypass — only access to settings and the pg_stat_* statistics views. On managed services (Amazon RDS, Cloud SQL, Azure) you grant it the same way.
Verify the role
Verify by connecting as the signals role in a fresh psql session, using the same host, database, and TLS settings the daemon will use. On RDS/Aurora a SET ROLE test from the admin user is not a reliable check, so connect as the role itself:
psql "host=<host> port=5432 dbname=<dbname> user=signals \
sslmode=verify-full sslrootcert=<ca-bundle.pem>"Then, in that session, read should succeed and every write must fail:
-- Should succeed (read access to monitoring views):
SELECT count(*) FROM pg_stat_database;
SELECT count(*) FROM pg_stat_activity;
-- Should ALL fail with permission denied (no write / DDL / admin):
CREATE TABLE _signals_role_check (id int);
INSERT INTO pg_class VALUES (NULL);
SELECT pg_terminate_backend(1);psql session as the role to report default_transaction_read_only = on. Signals enforces read-only at runtime on its own connections (it issues SET LOCAL default_transaction_read_only = on per transaction); a plain session does not set that, and it is not what makes the role safe — the privilege checks above are. See the read-only safety model.To confirm what the role can actually do, audit it directly against the catalog:
SELECT rolname, rolsuper, rolinherit, rolcreaterole,
rolcreatedb, rolcanlogin, rolreplication, rolbypassrls,
(SELECT array_agg(b.rolname)
FROM pg_auth_members m
JOIN pg_roles b ON m.roleid = b.oid
WHERE m.member = r.oid) AS memberships
FROM pg_roles r
WHERE rolname = 'signals';Expected:
rolsuper,rolcreaterole,rolcreatedb,rolreplication,rolbypassrlsare allf.membershipsincludespg_monitorand nothing that grants write access (pg_write_all_datais forbidden).
(Optional) Enable query statistics
pg_stat_statements adds query-level statistics. It is optional — Signals collects everything else without it, and the query-statistics collectors are skipped automatically rather than failing. The extension must be preloaded via shared_preload_libraries before it can be created:
- Self-managed PostgreSQL: add
pg_stat_statementstoshared_preload_librariesinpostgresql.conf, then restart the server. - RDS / Aurora: you do not edit
postgresql.conf. In a custom DB parameter group, addpg_stat_statementstoshared_preload_libraries, attach the group to the instance/cluster, and reboot if RDS marks the change pending-reboot.
Once the library is preloaded and the server has restarted, create the extension in the database you observe:
CREATE EXTENSION IF NOT EXISTS pg_stat_statements;pg_stat_statements installed, Signals still collects everything else; the query-statistics collectors are skipped automatically rather than failing.