Security & database access
You are about to give a stranger a connection string. Here is exactly what happens to it, and the least it can do.
Your connection string is never stored
It is used to run one checkup, held in memory for the few seconds that takes, and dropped. It is never written to disk, never written to logs, and never sent to any third party. Error messages are redacted before you see them, so a failed scan cannot leak your password back onto the screen.
Nothing about the credential survives the request. If you run a second checkup, you paste it again.
The exact permissions we need
One role, with one grant. pg_monitor is a built-in PostgreSQL role that can read statistics and configuration views. It cannot read the contents of your tables.
create role checkup_reader login password 'choose-a-strong-password';
grant pg_monitor to checkup_reader;
create extension if not exists pg_stat_statements;The pg_stat_statements extension is optional. Without it the checkup still runs, and the query findings are reported as unavailable rather than failing the scan.
We ask for nothing else. No superuser, no pg_read_all_data, no write permission of any kind.
The session cannot write
Every checkup session sets default_transaction_read_only = on before it does anything. Combined with a pg_monitor-only role, that is two independent reasons a checkup cannot modify your data: the role has no permission, and the session refuses writes.
Every diagnostic query also runs under a 15 second statement_timeout. A health check should never become the thing hurting the database it is checking.
What a checkup reads
Statistics and catalog views only, such as pg_stat_activity, pg_stat_user_tables, pg_stat_statements and pg_replication_slots. Never your table contents.
Two kinds of value get special handling before they reach your report:
- Settings that look like secrets are shown as
(hidden). That coversarchive_command,primary_conninfo, and anything whose name contains password, secret, token or key. - String literals in query text are masked in the database, before the text is sent to us. Running queries can contain email addresses, identifiers and API tokens as literal values, so a query arrives as
where email = '?'rather than with the real address in it.
Findings can still name tables, indexes and roles, and include normalized query shapes. That reveals schema detail, which is the point of a health check, so treat a report as you would treat a schema diagram.
What we store, and for how long
- The report lives under an unguessable link: 7 days with no account, 30 days with a free account, and permanently once you unlock it, until you delete it or your account. Anyone with the link can open it, so treat the link like a password.
- Your account, if you make one: email, an optional name, and either a password hash or your GitHub or Google id. Sessions are stored hashed.
- Payments are handled by Paystack. We receive confirmation that a payment succeeded, never your card details.
Good practice either way
- Create the role for the checkup, then rotate its password afterwards.
- Restrict it to the databases you want checked, where your host allows that.
- Point it at a replica if you have one.
Reporting a vulnerability
Email the address in the footer. Please do not test against databases you do not own.
The deeper technical reference, including TLS behaviour and the full list of views we query, is in the security docs. See also Privacy and Refunds.