Configuration
Each business metric in pg_exporter comes from a YAML collector definition.
A collector contains one SQL query and its execution conditions: version, role, tags, and predicates.
It also controls caching and timeout. This page describes all collector settings.
Use one YAML file, such as the default pg_exporter.yml, or a directory of YAML files.
The official default bundle combines 58 YAML files from config/ in lexicographic order: 57 collector files and one configuration reference. It defines 96 branches, 59 namespaces, and 460 distinct metric names, including disabled collectors and two unexpanded histogram definitions.
Configuration Loading
PG Exporter searches for configuration in the following order:
- Command-line argument:
--config=/path/to/config - Environment variable:
PG_EXPORTER_CONFIG=/path/to/config - Current directory:
./pg_exporter.yml - System config file:
/etc/pg_exporter.yml - System config directory:
/etc/pg_exporter/
Directory mode details:
- The exporter loads only
.yml/.yamlfiles in the specified directory. It does not read subdirectories. - It merges files in lexicographic order. A later file overrides an earlier collector definition with the same top-level name.
- If the directory contains YAML files but none can be parsed, the exporter returns an error.
- If only some files fail, the exporter logs their errors and loads the valid files. Directory loading is not all-or-nothing.
- An empty individual YAML file is a valid empty configuration; reloading it clears the collectors. A reload that fails parsing preserves the previous plan and caches.
Collector Structure
Define each collector as a top-level YAML object with a unique name and the required properties:
Validation rules:
- Each entry in
metricsmust define exactly one column mapping. - Each collector must expose at least one
GAUGE,COUNTER, orHISTOGRAMcolumn. usageaccepts onlyGAUGE,COUNTER,HISTOGRAM,LABEL, orDISCARD.- A
HISTOGRAMcolumn must definebucketwith finite upper bounds in strictly increasing order. The exporter appends the+Infbucket. - Metric and label names must follow Prometheus naming rules. The exporter checks them during loading and rejects invalid configurations immediately.
- Constant labels cannot conflict with query labels or built-in dynamic labels such as
datnameandquery. The exporter checks this during loading. If any collector usesHISTOGRAM,leis reserved and cannot be a constant label. - The SQL result must include every
LABELcolumn. Fromv1.4.1, a missing label column fails the entire collector scrape. The collector does not emit an empty label or keep stale results. Other non-fatal collectors continue. - In one-line inline
metricsdefinitions, enclosedescriptionvalues in double quotes to prevent YAML ambiguity.
Core Configuration Elements
Collector Branch Name
The top-level key uniquely identifies a collector across the entire configuration:
Query Definition
The SQL query that retrieves metrics:
Metric Types
Each column in the query result must be mapped to a metric type:
| Usage | Description | Example |
|---|---|---|
GAUGE | Instantaneous value that can go up or down | Current connections |
COUNTER | Cumulative value that only increases | Total transactions |
HISTOGRAM | Snapshot histogram deriving _bucket / _count / _sum series | Transaction age distribution |
LABEL | Use as a Prometheus label | Database name |
DISCARD | Ignore this column | Internal values |
Histogram Columns (HISTOGRAM)
Version v1.4.0 adds the HISTOGRAM column type.
Each query result row is one observation. The exporter groups observations by label to produce a classic Prometheus histogram snapshot.
It generates three series families: <name>_bucket, <name>_count, and <name>_sum.
The bucket series includes the le label and the +Inf bucket:
Usage notes:
- This is a snapshot histogram. Each scrape rebuilds the full distribution. Bucket counts can increase or decrease, as gauges do. Use
histogram_quantile()directly. Do not userate()/increase()on_count/_sum; these operations have no meaning for a snapshot. - By default, the exporter ignores SQL
NULLobservations. If you setdefault, it counts them with that value. - The exporter applies
scalebefore it assigns a bucket. As with scalar columns,scaledoes not apply to timestamps or booleans. - For a reference implementation, see the default
pg_xact_agecollector.
Cache Control (TTL)
The ttl parameter controls result caching:
Best practices:
- Set TTL less than your scrape interval
- Use longer TTL for expensive queries
- TTL of 0 disables caching
- Collector and predicate TTLs must be finite, nonnegative, and fit in Go
time.Duration. v1.5.0 rejects NaN, infinities, and excessively large values.
Timeout Control
Prevent queries from running too long:
Omitting timeout or setting it to 0 selects the 100ms default; a finite negative value disables the query deadline. v1.5.0 rejects NaN, infinities, and positive timeouts that would overflow. The timeout covers the predicates and main query together.
Version Compatibility
Control which PostgreSQL versions can run this collector:
Version numbers follow PostgreSQL server_version_num rules:
100000= 10.0130002= 13.2160001= 16.1190000= 19.090600= 9.6, relevant when using the legacy config bundle
Execution Model
Use the execution model to find why a metric is missing:
- Planning runs on the first scrape, configuration reload, or metadata change. It checks each branch’s target type (PostgreSQL / pgBouncer),
min_version/max_version,tags, andskipsetting. Tags must match the server role and exporter tags. A branch that fails any check is not installed on the target. Usecurl localhost:9630/explainto see each decision. - Scraping runs on each
/metricsrequest. An installed collector returns cached results while they are withinttl. Otherwise, it first runspredicate_queries. A false result skips the collector for this round and incrementspg_exporter_query_scrape_predicate_skip_count. If all predicates pass, the main query runs withtimeout. The exporter converts the results to metrics and caches them. - Failure semantics: a normal collector failure affects only that collector. It increments
pg_exporter_query_scrape_error_countand omits its metric group for this round. A failed collector withfatal: truefails the entire server scrape.
In v1.5.0, a successful precheck compares the username, schemas, and extensions. A change triggers replanning; adding or removing a schema or extension does not require a manual reload. Unchanged sets preserve plans and caches; replanning resets query caches and statistics.
Tag System
Tags control when and where collectors execute:
Built-in Tags
| Tag | Description |
|---|---|
cluster | Execute once per PostgreSQL cluster |
primary / master | Only on primary servers |
standby / replica | Only on replica servers |
pgbouncer | Only for pgBouncer connections |
Prefixed Tags
| Prefix | Example | Description |
|---|---|---|
dbname: | dbname:postgres | Only on specific database |
username: | username:monitor | Only with specific user |
extension: | extension:pg_stat_statements | Only if extension installed |
schema: | schema:public | Only if schema exists |
not: | not:slow | NOT when exporter has tag |
Custom Tags
Pass custom tags to the exporter:
Then use the tags in the configuration:
Predicate Queries
Run conditional checks before the main query:
The main query only executes if all predicates return true.
Metric Definition
Basic Definition
Advanced Options
Collector Organization
PG Exporter ships with pre-organized collectors:
| Range | Category | Description |
|---|---|---|
| 0xx | Documentation | Examples and documentation |
| 1xx | Basic | Server info, settings, metadata |
| 2xx | Replication | Replication, slots, receivers |
| 3xx | Persistence | I/O, checkpoints, WAL |
| 4xx | Activity | Connections, locks, queries |
| 5xx | Progress | Vacuum, index creation progress |
| 6xx | Database | Per-database statistics |
| 7xx | Objects | Tables, indexes, functions |
| 8xx | Optional | Expensive/optional metrics |
| 9xx | pgBouncer | Connection pooler metrics |
| 10xx+ | Extensions | Extension-specific metrics |
Real-World Examples
Simple Gauge Collector
Counter with Labels
Version-Specific Collector
Extension-Dependent Collector
Custom Collectors
Creating Your Own Metrics
- Create a new YAML file in your config directory:
- Test your collector:
Conditional Metrics
Use predicate queries for conditional metrics:
Performance Optimization
Query Optimization Tips
Use appropriate TTL values:
- Fast queries: 1-10 seconds
- Medium queries: 10-60 seconds
- Expensive queries: 300-3600 seconds
Set realistic timeouts:
- Default: 100ms
- Complex queries: 500ms-1s
- Never disable timeout in production
Use cluster-level tags:
Disable expensive collectors:
Monitoring Collector Performance
Check collector execution statistics:
Metric and Alert Upgrade Checks
When upgrading the exporter, merge and deploy the matching collector YAML. Replacing only the binary does not apply SQL, label, or state-code corrections. For instances managed by Pigsty, also verify that the deployed configuration contains these definitions. After a PostgreSQL major-version upgrade, check the newly selected collector branches.
- Exporter v1.4.1 → v1.5.0: bundled SQL metric names, types, and units stay unchanged, but
pg_sub_*addsdatnameandpg_recv_statecorrects its state codes. Review joins/aggregations for subscriptions with the same name in different databases, and Grafana value mappings. - PG18 → PG19: existing metrics are not removed or renamed, but
pg_sub_sync_error_countbroadens to table plus sequence synchronization errors, andpg_subrel_countincludes sequences.pg_sub_has_workerdistinguishes a subscription row from a running apply worker; the presence ofpg_sub_idalone is insufficient. - Crossing PG17 / PG18: some
pg_bgwriter_*metrics need to move topg_checkpointer_*or backend-filtered I/O metrics. From PG18 onward,pg_wal_write,pg_wal_sync,pg_wal_write_time, andpg_wal_sync_timeneed to move topg_io_*{object="wal"}, with corresponding label aggregation changes. See the metric-by-metric migration table.
See the v1.5.0 release notes and PG19 metric table for the full changes. PG19 support first shipped in v1.3.0, and acceptance evidence refers to 19 RC1; these notes do not establish runtime validation of every dashboard.
Before and after deployment, inspect /metrics, /explain, /stat, pg_exporter_query_scrape_error_count, and the logs. Evaluate the actual dashboard, recording-rule, and alert expressions, checking returned series, labels, units, and state mappings. Use promtool check rules for syntax and promtool test rules for both normal and missing-series input. HTTP 200, up == 1, or pg_up == 1 does not prove that every expected metric exists; an empty vector is not a healthy zero.
For PG19 targets expected to expose the bundled WAL collector, use this per-target missing-metric check with for: 5m in the alert rule:
job="pg19" is an example: replace it with the actual target selector and include any additional identity labels in matching. Monitor up and pg_up failures separately. Scope absence checks by version, primary/replica role, and expected objects; for example, a primary should not require pg_recovery_state_*. Do not mask missing input with an unconditional or vector(0). Fleet-wide absent(metric) also misses one target’s disappearance while other targets still emit data. See the complete missing-metric rule.
Troubleshooting Configuration
Validate Configuration
Common Issues
| Problem | Solution |
|---|---|
| Metrics missing | Check tags and version compatibility |
| Slow scrapes | Increase TTL, add timeout, disable expensive queries |
| High memory usage | Reduce result set size, use LIMIT |
| Permission errors | Verify query permissions for monitoring user |
Debug Logging
Enable debug logging to troubleshoot:
Was this page helpful?
Thanks—your feedback helps us improve this page.
What got in the way? (optional)