Configuration

All configuration is supplied through environment variables prefixed with QUERYINSIGHTS_. Only one is strictly required; everything else has a sensible default or unlocks an optional capability.

Never hard-code secrets. Provide API keys and database passwords through a secret manager or your platform's environment configuration — not in source control or shell history.

Core

VariableRequiredDefaultDescription
QUERYINSIGHTS_DB_URLYesConnection string for the QueryInsights metastore (PostgreSQL).
QUERYINSIGHTS_LISTEN_ADDRESSNo0.0.0.0:2427Address the webhook service listens on.
QUERYINSIGHTS_ENGINE_ADDRESSNolocalhost:50051Engine gRPC address used by the poller, webhook, and dashboard.
QUERYINSIGHTS_DASHBOARD_ADDRESSNo:3001Address the dashboard API listens on.

LLM

VariableRequiredDefaultDescription
QUERYINSIGHTS_OPENAI_API_KEYNoEnables OpenAI recommendations.
QUERYINSIGHTS_ANTHROPIC_API_KEYNoEnables Anthropic (Claude) recommendations.
QUERYINSIGHTS_LLM_MODELNogpt-4o-miniChat model for recommendations. Also selects the provider (see below).
QUERYINSIGHTS_LLM_BASE_URLNoCustom base URL for the LLM client — point it at a gateway such as LiteLLM or Portkey.

How the provider is chosen

The engine picks a backend from the model name:

  • Model name contains claude and QUERYINSIGHTS_ANTHROPIC_API_KEY is set → Anthropic.
  • Model name contains claude but only QUERYINSIGHTS_OPENAI_API_KEY is set → OpenAI-compatible client (use this when a gateway fronts Claude behind an OpenAI-compatible API, e.g. a model name like vertex/claude-opus-4).
  • Otherwise → OpenAI.

If no matching API key is configured, the engine starts without recommendation features; ingestion and the dashboard still work.

Metadata sources

VariableRequiredDefaultDescription
QUERYINSIGHTS_TRINO_URLNoTrino coordinator URL, used to fetch table DDL for Trino recommendations.
QUERYINSIGHTS_COCKROACH_INSTANCESNoJSON array of CockroachDB instances to poll and read schema from.
QUERYINSIGHTS_POSTGRES_INSTANCESNoJSON array of PostgreSQL instances to poll and read schema from.

Recommendation tuning

VariableRequiredDefaultDescription
QUERYINSIGHTS_REC_MAX_ATTEMPTSNo3Failed per-query recommendation attempts before a pattern is permanently skipped.
QUERYINSIGHTS_DDL_MAX_FAILURESNo3Consecutive SHOW CREATE TABLE failures for a table before schema fetching is abandoned.
QUERYINSIGHTS_STATS_CACHE_TTL_SECSNo1800How long rendered table-statistics blocks are cached before re-fetching.
QUERYINSIGHTS_WORKLOAD_INTERVAL_MINNo10080Minutes between periodic workload-insight runs. Set to 0 to disable the ticker.
QUERYINSIGHTS_WORKLOAD_TOP_TABLESNo10Number of hottest tables included in each workload profile.
QUERYINSIGHTS_WORKLOAD_TOP_QUERIES_PER_TABLENo5Top normalized patterns per table included in the workload prompt.

Describing database instances

Both QUERYINSIGHTS_COCKROACH_INSTANCES and QUERYINSIGHTS_POSTGRES_INSTANCES take a JSON array of objects with the same shape:

[
  {
    "name": "production",
    "dsn": "postgres://queryinsights:REPLACE_WITH_PASSWORD@db.internal:5432/appdb?sslmode=require",
    "sampling_rate": 0.5,
    "poll_interval_seconds": 10
  }
]
FieldTypeDescription
namestringA label for the instance; shown in the dashboard and stored with every captured query.
dsnstringConnection string. The user in this DSN needs both statement-stats access and schema-read access.
sampling_ratenumberFraction of captured queries to keep, 0.01.0 (1.0 = keep everything). Values outside this range fall back to 1.0.
poll_interval_secondsnumberHow often to poll the statistics table. Defaults to 10 when unset or non-positive.

You can configure multiple instances, and both engines at once — the poller starts one goroutine per instance.

The same DSN user is used by the poller (to read statistics) and by the engine (to read table DDL). Follow the least-privilege setup in Onboarding PostgreSQL and Onboarding CockroachDB to create that user safely.

Example

export QUERYINSIGHTS_DB_URL="postgres://queryinsights:REPLACE_WITH_PASSWORD@localhost:5432/metastore?sslmode=disable"
export QUERYINSIGHTS_LLM_MODEL="gpt-4o-mini"
export QUERYINSIGHTS_OPENAI_API_KEY="REPLACE_WITH_OPENAI_API_KEY"

export QUERYINSIGHTS_POSTGRES_INSTANCES='[
  {"name":"prod","dsn":"postgres://queryinsights:REPLACE_WITH_PASSWORD@db.internal:5432/appdb?sslmode=require","sampling_rate":1.0,"poll_interval_seconds":10}
]'

Keep the real values in a secret store and inject them at runtime.