Collector
The Collector is the only part of Query Doctor that touches your database. It reads the schema, the table statistics and the query text, sends them to your Query Doctor instance, and analyzes none of it: the planning and costing happen on the instance, against a Postgres of its own.
The image is ghcr.io/query-doctor/collector.
Two modes
Section titled “Two modes”Monitor stands beside a live database and checks in once a minute. You do not start it. Connecting a database in the app stores the connection string, and the instance runs the container itself against that database. See Getting Started.
CI runs once inside a job, captures the queries that job’s tests executed against its own Postgres service, and reports the verdict back to the pull request. This is the one you run yourself, as a step in your workflow. See CI integration.
Both report over the same HTTP endpoint, and neither holds a socket open for anything to call back down.
What it reads
Section titled “What it reads”- Schema — tables, columns, indexes, constraints, functions, views, types, triggers, and extensions, read from the catalog.
- Query statistics — recent queries and their execution metrics from the
pg_stat_statementsextension. Note thatpg_stat_statementscan contain real query text, including literal parameter values depending on your PostgreSQL configuration. - Table statistics — row estimates and the contents of
pg_statistic, used for query plan analysis. These are real values read from your database.
Each read stands on its own. A database without pg_stat_statements still sends its schema and statistics; a statistics dump that fails on a statement timeout does not cost the check-in the queries it was about to deliver.
What leaves your database
Section titled “What leaves your database”All three go to the Query Doctor instance the Collector was told to report to, which stores them against your project. That is https://cloud.querydoctor.com on the hosted service, or your own instance’s address if you self-host. The table statistics carry the most sensitive data: pg_statistic rows include the most common values and histogram bounds Postgres sampled from your columns, so they contain real values out of your tables.
The TOKEN the container carries authenticates that upload. No setting keeps the data on your machine.
What it writes to your database
Section titled “What it writes to your database”Nothing. Both modes read.
Installing pg_stat_statements is yours to do. CREATE EXTENSION and ALTER SYSTEM SET shared_preload_libraries both need a superuser, so the app shows you the SQL when it notices the extension is missing.
Costing candidate indexes writes nothing here either. Query Doctor replays your schema into a Postgres of its own, creates the candidate indexes there, and throws the database away. Your rows never reach it: only the schema, the statistics and the query text are sent.
Configuration
Section titled “Configuration”| Variable | What it is |
|---|---|
SOURCE_DATABASE_URL |
The database to read. Required in both modes. |
SITE_API_ENDPOINT |
The Query Doctor instance this run reports to. Required in both modes. |
TOKEN |
The project’s analyzer token, which authorizes the upload. Required in monitor mode. |
CI |
true selects CI mode. A container step does not inherit the runner’s, so a workflow sets it itself. |
The container exits at startup without the first two. In monitor mode the instance fills all of them in; in CI they are the step’s env block, which CI integration shows whole.
Prerequisites on the source database
Section titled “Prerequisites on the source database”-
pg_stat_statementsextension — required for query statistics. Install it with:CREATE SCHEMA IF NOT EXISTS ext;CREATE EXTENSION IF NOT EXISTS pg_stat_statements SCHEMA ext;The Collector resolves the extension’s schema from
pg_extension, so it reads the statistics wherever they are. Keep them out ofpublic, where the extension’s views break migration tools that reconcile that schema (see Enabling pg_stat_statements).The extension must also be added to
shared_preload_librariesin your PostgreSQL config, which requires a server restart. -
Database access — the user in your connection string needs read access to the schema and the statistics views. Nothing the Collector does needs more than that.