Skip to content

This is the multi-page printable view of this section. .

Return to the regular view of this page.

PG Exporter 1.4 Documentation

Advanced PostgreSQL & pgBouncer Metrics Exporter for Prometheus

Monitor PostgreSQL with 600+ metrics, declarative configuration, and dynamic planning.

Get Started | GitHub | Live Demo


Features

FeatureDescription
Comprehensive Metrics600+ metrics cover nearly every statistics view in PostgreSQL (10-19+) and pgBouncer (1.8-1.25+)
Declarative CollectorsDefine each metric in a YAML collector with a SQL query and execution conditions. Add, change, or remove metrics without code changes
Dynamic PlanningSelect each collector branch for a target by version, primary/replica role, installed extensions, and tags
Auto-DiscoveryDiscover and scrape each database in an instance. The datname label identifies the database
Health Check APIsUse /up, /primary, and /replica as load-balancer probes to route primary/replica traffic
Smart CachingCache each collector by TTL. Frequent probes and scrapes do not cause an equal number of database queries
Snapshot HistogramsUse the HISTOGRAM column type to aggregate SQL snapshots into classic Prometheus histogram distributions
Extension AwareNative support for pg_stat_statements, pg_wait_sampling, citus, and timescaledb
Production ReadyUsed in production on 12K+ cores for 6+ years

Version Info

  • Current stable release: v1.4.1
  • Default config support: PostgreSQL 10-19+
  • Legacy config support: PostgreSQL 9.1-9.6 via the legacy/ config bundle
  • pgBouncer support: 1.8-1.25+

See Release Notes for the full history.


Design Rationale

pg_exporter uses these principles for production deployments:

  • Local connections: if no URL is specified, use postgresql:///?sslmode=disable for a database on the same host.
  • Declarative collection: use YAML collector definitions to control metric behavior with ttl, timeout, tags, and fatal.
  • Dynamic planning: select the collector branch at runtime from the server version, role, extensions, and tags.
  • Operation during failure: startup is non-blocking by default. HTTP endpoints start even if the database is temporarily unavailable.
  • Hot reload: use POST / GET /reload or SIGHUP to reload. Non-Windows platforms also support SIGUSR1.
  • Separate probes from traffic: health endpoints use cached background probes. Each request does not need a database query.
  • Protect management endpoints: /reload, /explain, and /stat expose runtime and configuration details. In production, protect them with --web.config.file or keep them internal.

Installation

Select an installation method for your infrastructure:

Docker
docker run -d --name pg_exporter -p 9630:9630 -e PG_EXPORTER_URL="postgres://user:pass@host:5432/postgres" pgsty/pg_exporter:latest
YUM
# RPM-based systems
sudo tee /etc/yum.repos.d/pigsty-infra.repo > /dev/null <<-'EOF'
[pigsty-infra]
name=Pigsty Infra for $basearch
baseurl=https://repo.pigsty.io/yum/infra/$basearch
enabled = 1
gpgcheck = 0
module_hotfixes=1
EOF

sudo yum makecache;
sudo yum install -y pg_exporter
APT
sudo tee /etc/apt/sources.list.d/pigsty-infra.list > /dev/null <<EOF
deb [trusted=yes] https://repo.pigsty.io/apt/infra generic main
EOF

sudo apt update;
sudo apt install -y pg-exporter
Binary
VERSION=$(curl -fsSL https://api.github.com/repos/pgsty/pg_exporter/releases/latest | sed -n 's/.*"tag_name": "v\([^"]*\)".*/\1/p')
wget "https://github.com/pgsty/pg_exporter/releases/download/v${VERSION}/pg_exporter-${VERSION}.linux-amd64.tar.gz"
mkdir -p "pg_exporter-${VERSION}.linux-amd64"
tar -xf "pg_exporter-${VERSION}.linux-amd64.tar.gz" -C "pg_exporter-${VERSION}.linux-amd64"
sudo install "pg_exporter-${VERSION}.linux-amd64/pg_exporter" /usr/bin/
sudo install "pg_exporter-${VERSION}.linux-amd64/pg_exporter.yml" /etc/pg_exporter.yml
Source
# Build from source
git clone https://github.com/pgsty/pg_exporter.git
cd pg_exporter
make build

Quick Start

Follow Getting Started to start PG Exporter:

# Minimal startup with the local-first default URL
pg_exporter

# Or point to a specific target
PG_EXPORTER_URL='postgres://user:pass@localhost:5432/postgres' pg_exporter

# Access metrics
curl http://localhost:9630/metrics

# Reload configuration online (POST recommended)
curl -X POST http://localhost:9630/reload

Documentation


Live Demo

Open the PG Exporter demo: https://g.pgsty.com

The demo monitors real PostgreSQL clusters with PG Exporter. It includes:

  • Real-time metrics visualization with Grafana
  • Multiple PostgreSQL versions and configurations
  • Extension-specific metrics and monitoring
  • Complete observability stack powered by Pigsty

Community & Support

  • GitHub - Source code, issues, and contributions
  • Discussions - Ask questions and share experiences
  • Pigsty - Complete PostgreSQL Distro with PG Exporter

License

PG Exporter is open-source software licensed under the Apache License 2.0.

Copyright 2018-2026 © Ruohang Feng / [email protected]

1 - Getting Started

Get pg_exporter running and see PostgreSQL metrics in Prometheus within ten minutes

Follow these steps to install pg_exporter, connect to PostgreSQL, check metrics, and configure Prometheus.

You need a reachable PostgreSQL 10-19+ or pgBouncer 1.8+ instance and permission to create a user in it. For PostgreSQL 9.1-9.6, see Compatibility.


Step 1: Install

On Linux amd64, download the binary directly. For other platforms and RPM/DEB/Docker options, see the Installation guide.

VERSION=$(curl -fsSL https://api.github.com/repos/pgsty/pg_exporter/releases/latest | sed -n 's/.*"tag_name": "v\([^"]*\)".*/\1/p')
wget "https://github.com/pgsty/pg_exporter/releases/download/v${VERSION}/pg_exporter-${VERSION}.linux-amd64.tar.gz"
mkdir -p "pg_exporter-${VERSION}.linux-amd64"
tar -xf "pg_exporter-${VERSION}.linux-amd64.tar.gz" -C "pg_exporter-${VERSION}.linux-amd64"
sudo install "pg_exporter-${VERSION}.linux-amd64/pg_exporter" /usr/bin/
sudo install "pg_exporter-${VERSION}.linux-amd64/pg_exporter.yml" /etc/pg_exporter.yml

Confirm the installation:

pg_exporter --version
# pg_exporter v1.4.1 (built with go1.26.5 on linux/amd64)

Step 2: Create a Monitoring User

Create a dedicated monitoring user on the target PostgreSQL instance. The built-in pg_monitor role in PostgreSQL 10+ gives the user all read permissions that the default collectors need:

CREATE USER monitor WITH PASSWORD 'S3cret';
GRANT pg_monitor TO monitor;

For a local test with a superuser such as postgres, you can skip this step.


Step 3: Run and Verify

Use --dry-run to check that the configuration parses correctly. Then start the exporter:

export PG_EXPORTER_URL='postgres://monitor:S3cret@localhost:5432/postgres'

pg_exporter --dry-run     # print parsed collector config, then exit
pg_exporter               # start for real, listening on :9630 by default

If you do not specify a URL, pg_exporter uses postgresql:///?sslmode=disable to connect on the same host. The URL source order is --url > PG_EXPORTER_URL > PGURL > PG_EXPORTER_URL_FILE > default. See the Deployment guide for details.

Get the metrics from another terminal:

curl -s http://localhost:9630/metrics | grep -E '^pg_(up|version|in_recovery) '

You should see the three core built-in metrics:

pg_up 1              # 1 when the target is reachable, 0 otherwise
pg_version 170000    # version in server_version_num format
pg_in_recovery 0     # 1 on replicas, 0 on primaries

pg_up 1 shows that the connection and metric collection work. The remaining 600+ metrics (pg_db_*, pg_table_*, pg_wal_*, …) come from collector definitions in pg_exporter.yml. If pg_up is 0, restart with pg_exporter --log.level=debug and examine the connection error.


Step 4: Hook into Prometheus

Add a scrape target in prometheus.yml:

scrape_configs:
  - job_name: 'postgresql'
    scrape_interval: 15s
    static_configs:
      - targets: ['localhost:9630']

Collectors cache results for their ttl. Most realtime collectors use ttl: 10. If the TTL is less than the scrape interval, each scrape gets fresh data. The cache also prevents high-frequency scrapes from overloading the database. Do not set scrape_interval below the common collector TTLs.

For Grafana, use the PostgreSQL dashboards from Pigsty, or view the live demo.


Troubleshooting

SymptomWhat to do
pg_up 0, connection failsRun pg_exporter --log.level=debug and read the error; check URL, pg_hba.conf, and network reachability
Some metrics are missingcurl localhost:9630/explain to see each collector’s planning verdict (version gates, tags, predicates)
A collector keeps failingcurl localhost:9630/stat for per-collector error counters and durations
Scrapes are slowFind the slow collector in /stat, raise its ttl, or set skip: true

/stat, /explain, and /reload are management endpoints. In production, protect them with --web.config.file for TLS/auth, or keep them on a trusted network. See the API Reference.


Next Steps

  • Monitor pgBouncer, enable auto-discovery, deploy with systemd / Docker / Kubernetes: Deployment guide
  • Understand and customize collectors (GAUGE/COUNTER/HISTOGRAM, TTL, tags, version gates): Configuration reference
  • Health check and primary/replica traffic routing endpoints (/up, /primary, /replica): API Reference

2 - Installation

How to download and install the pg_exporter

Install pg_exporter with Pigsty, YUM/APT repositories, GitHub release packages (RPM/DEB/Tarball), or Docker images. You can also build it from source.

Pigsty

Use Pigsty for the simplest installation. Pigsty is a complete PostgreSQL distribution with monitoring based on pg_exporter, Prometheus, and Grafana. It configures the metrics and dashboard panels for you. You do not need to configure pg_exporter separately.

curl -fsSL https://repo.pigsty.io/get | bash; cd ~/pigsty;

Release

Download a pg_exporter package (RPM/DEB/Tarball) from the Latest GitHub Release Page:

v1.4.1 Release Files:

Install the package with your OS package manager (rpm/dpkg), or put the binary in your $PATH. Current tarballs also include pg_exporter.yml, package/pg_exporter.default, package/pg_exporter.service, and LICENSE for manual deployments.

RPM package rename

From v1.4.1, the official RPM package name and artifact prefix are pg-exporter, instead of pg_exporter. This name matches the DEB package and repository installation commands. The new RPM provides and obsoletes the legacy pg_exporter package name. You can upgrade directly from earlier releases.

The release page contains full SHA256 checksums in checksums.txt. The release notes also contain checksums for each version.

Repository

The pigsty-infra repository also contains the pg_exporter package. Add the repository to your system. Then install the package with your OS package manager:

YUM

For EL distributions such as RHEL, Rocky Linux, CentOS, AlmaLinux, and Oracle Linux:

sudo tee /etc/yum.repos.d/pigsty-infra.repo > /dev/null <<-'EOF'
[pigsty-infra]
name=Pigsty Infra for $basearch
baseurl=https://repo.pigsty.io/yum/infra/$basearch
enabled = 1
gpgcheck = 0
module_hotfixes=1
EOF

sudo yum makecache;
sudo yum install -y pg_exporter

APT

For Debian, Ubuntu and compatible Linux Distributions:

sudo tee /etc/apt/sources.list.d/pigsty-infra.list > /dev/null <<EOF
deb [trusted=yes] https://repo.pigsty.io/apt/infra generic main
EOF

sudo apt update;
sudo apt install -y pg-exporter

Docker

Docker Hub provides prebuilt images for the amd64 and arm64 architectures: pgsty/pg_exporter.

# Basic usage
docker run -d \
  --name pg_exporter \
  -p 9630:9630 \
  -e PG_EXPORTER_URL="postgres://user:password@host:5432/postgres" \
  pgsty/pg_exporter:latest

# With custom configuration
docker run -d \
  --name pg_exporter \
  -p 9630:9630 \
  -v /path/to/pg_exporter.yml:/etc/pg_exporter.yml:ro \
  -e PG_EXPORTER_CONFIG="/etc/pg_exporter.yml" \
  -e PG_EXPORTER_URL="postgres://user:password@host:5432/postgres" \
  pgsty/pg_exporter:latest

# With auto-discovery enabled
docker run -d \
  --name pg_exporter \
  -p 9630:9630 \
  -e PG_EXPORTER_URL="postgres://user:password@host:5432/postgres" \
  -e PG_EXPORTER_AUTO_DISCOVERY="true" \
  -e PG_EXPORTER_EXCLUDE_DATABASE="template0,template1" \
  pgsty/pg_exporter:latest
Warning

The current Docker image is built from scratch. To connect to remote PostgreSQL with sslmode=verify-ca or verify-full, mount a CA certificate explicitly. Use sslrootcert or a system CA bundle. Without this certificate, TLS verification can fail.

Compatibility

The default configuration supports PostgreSQL 10-19+. For PostgreSQL versions that have reached EOL, use the bundled legacy/ configuration package.

PostgreSQL VersionSupport Status
10 ~ 19+✅ Full Support (default config)
9.1 ~ 9.6⚠️ Use legacy/pg_exporter.yml
9.0 and earlier❌ Unsupported

Legacy config example:

make conf9
PG_EXPORTER_CONFIG=legacy/pg_exporter.yml pg_exporter

pg_exporter supports pgBouncer 1.8+. Version v1.8 is the first pgBouncer version with SHOW command support.

pgBouncer VersionSupport Status
1.8.x ~ 1.25+✅ Full Support
before 1.8.x⚠️ No Metrics

3 - 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 definition files from config/.

Configuration Loading

PG Exporter searches for configuration in the following order:

  1. Command-line argument: --config=/path/to/config
  2. Environment variable: PG_EXPORTER_CONFIG=/path/to/config
  3. Current directory: ./pg_exporter.yml
  4. System config file: /etc/pg_exporter.yml
  5. System config directory: /etc/pg_exporter/

Directory mode details:

  • The exporter loads only .yml / .yaml files 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.

Collector Structure

Define each collector as a top-level YAML object with a unique name and the required properties:

collector_branch_name:           # Unique identifier for this collector
  name: metric_namespace         # Metric prefix (defaults to branch name)
  desc: "Collector description"  # Human-readable description
  query: |                       # SQL query to execute
    SELECT column1, column2
    FROM table

  # Execution Control
  ttl: 10                        # Cache time-to-live in seconds
  timeout: 0.1                   # Query timeout in seconds
  fatal: false                   # If true, failure fails entire scrape
  skip: false                    # If true, collector is disabled

  # Version Compatibility
  min_version: 100000            # Minimum PostgreSQL version (inclusive)
  max_version: 999999            # Maximum PostgreSQL version (exclusive)

  # Execution Tags
  tags: [cluster, primary]       # Conditions for execution

  # Predicate Queries (optional)
  predicate_queries:
    - name: "check_function"
      predicate_query: |
        SELECT EXISTS (...)

  # Metric Definitions
  metrics:
    - column_name:
        usage: GAUGE             # GAUGE, COUNTER, HISTOGRAM, LABEL, or DISCARD
        rename: metric_name      # Optional: rename the metric
        description: "Help text" # Metric description
        default: 0               # Default value if NULL
        scale: 1000              # Scale factor for the value
        bucket: [1, 10, 100]     # Bucket upper bounds for HISTOGRAM columns (strictly increasing, +Inf appended)

Validation rules:

  • Each entry in metrics must define exactly one column mapping.
  • Each collector must expose at least one GAUGE, COUNTER, or HISTOGRAM column.
  • usage accepts only GAUGE, COUNTER, HISTOGRAM, LABEL, or DISCARD.
  • A HISTOGRAM column must define bucket with finite upper bounds in strictly increasing order. The exporter appends the +Inf bucket.
  • 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 datname and query. The exporter checks this during loading. If any collector uses HISTOGRAM, le is reserved and cannot be a constant label.
  • The SQL result must include every LABEL column. From v1.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 metrics definitions, enclose description values 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:

pg_stat_database:  # Must be unique
  name: pg_db      # Actual metric namespace

Query Definition

The SQL query that retrieves metrics:

query: |
  SELECT 
    datname,
    numbackends,
    xact_commit,
    xact_rollback,
    blks_read,
    blks_hit
  FROM pg_stat_database
  WHERE datname NOT IN ('template0', 'template1')

Metric Types

Each column in the query result must be mapped to a metric type:

UsageDescriptionExample
GAUGEInstantaneous value that can go up or downCurrent connections
COUNTERCumulative value that only increasesTotal transactions
HISTOGRAMSnapshot histogram deriving _bucket / _count / _sum seriesTransaction age distribution
LABELUse as a Prometheus labelDatabase name
DISCARDIgnore this columnInternal 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:

pg_xact_age:
  name: pg_xact_age
  desc: "Open transaction age distribution histogram"
  query: |
    SELECT datname,
           greatest(0, extract(epoch FROM now() - xact_start)) AS seconds
    FROM pg_stat_activity
    WHERE pid <> pg_backend_pid() AND backend_type = 'client backend'
      AND datname IS NOT NULL AND xact_start IS NOT NULL;
  ttl: 10
  tags: [cluster]
  metrics:
    - datname: {usage: LABEL, description: "Database name"}
    - seconds:
        usage: HISTOGRAM
        bucket: [1, 3, 10, 30, 100, 300, 1000, 3000, 10000, 30000, 100000]
        description: "Open transaction age snapshot in seconds"

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 use rate() / increase() on _count / _sum; these operations have no meaning for a snapshot.
  • By default, the exporter ignores SQL NULL observations. If you set default, it counts them with that value.
  • The exporter applies scale before it assigns a bucket. As with scalar columns, scale does not apply to timestamps or booleans.
  • For a reference implementation, see the default pg_xact_age collector.

Cache Control (TTL)

The ttl parameter controls result caching:

# Fast queries - minimal caching
pg_stat_activity:
  ttl: 1  # Cache for 1 second

# Expensive queries - longer caching
pg_table_bloat:
  ttl: 3600  # Cache for 1 hour

Best practices:

  • Set TTL less than your scrape interval
  • Use longer TTL for expensive queries
  • TTL of 0 disables caching

Timeout Control

Prevent queries from running too long:

timeout: 0.1   # 100ms default
timeout: 1.0   # 1 second for complex queries
timeout: -1    # Disable timeout (not recommended)

Version Compatibility

Control which PostgreSQL versions can run this collector:

min_version: 100000  # PostgreSQL 10.0+
max_version: 140000  # Below PostgreSQL 14.0

Version numbers follow PostgreSQL server_version_num rules:

  • 100000 = 10.0
  • 130200 = 13.2
  • 160100 = 16.1
  • 190000 = 19.0
  • 90600 = 9.6, relevant when using the legacy config bundle

Execution Model

Use the execution model to find why a metric is missing:

  1. Planning runs when the connection starts or configuration reloads. It checks each branch’s target type (PostgreSQL / pgBouncer), min_version / max_version, tags, and skip setting. Tags must match the server role and exporter tags. A branch that fails any check is not installed on the target. Use curl localhost:9630/explain to see each decision.
  2. Scraping runs on each /metrics request. An installed collector returns cached results while they are within ttl. Otherwise, it first runs predicate_queries. A false result skips the collector for this round and increments pg_exporter_query_scrape_predicate_skip_count. If all predicates pass, the main query runs with timeout. The exporter converts the results to metrics and caches them.
  3. Failure semantics: a normal collector failure affects only that collector. It increments pg_exporter_query_scrape_error_count and omits its metric group for this round. A failed collector with fatal: true fails the entire server scrape.

Tag System

Tags control when and where collectors execute:

Built-in Tags

TagDescription
clusterExecute once per PostgreSQL cluster
primary / masterOnly on primary servers
standby / replicaOnly on replica servers
pgbouncerOnly for pgBouncer connections

Prefixed Tags

PrefixExampleDescription
dbname:dbname:postgresOnly on specific database
username:username:monitorOnly with specific user
extension:extension:pg_stat_statementsOnly if extension installed
schema:schema:publicOnly if schema exists
not:not:slowNOT when exporter has tag

Custom Tags

Pass custom tags to the exporter:

pg_exporter --tag="production,critical"

Then use the tags in the configuration:

expensive_metrics:
  tags: [critical]  # Only runs with 'critical' tag

Predicate Queries

Run conditional checks before the main query:

predicate_queries:
  - name: "Check pg_stat_statements"
    predicate_query: |
      SELECT EXISTS (
        SELECT 1 FROM pg_extension 
        WHERE extname = 'pg_stat_statements'
      )

The main query only executes if all predicates return true.

Metric Definition

Basic Definition

metrics:
  - numbackends:
      usage: GAUGE
      description: "Number of backends connected"

Advanced Options

metrics:
  - checkpoint_write_time:
      usage: COUNTER
      rename: write_time        # Rename metric
      scale: 0.001              # Convert ms to seconds
      default: 0                # Use 0 if NULL
      description: "Checkpoint write time in seconds"

Collector Organization

PG Exporter ships with pre-organized collectors:

RangeCategoryDescription
0xxDocumentationExamples and documentation
1xxBasicServer info, settings, metadata
2xxReplicationReplication, slots, receivers
3xxPersistenceI/O, checkpoints, WAL
4xxActivityConnections, locks, queries
5xxProgressVacuum, index creation progress
6xxDatabasePer-database statistics
7xxObjectsTables, indexes, functions
8xxOptionalExpensive/optional metrics
9xxpgBouncerConnection pooler metrics
10xx+ExtensionsExtension-specific metrics

Real-World Examples

Simple Gauge Collector

pg_connections:
  desc: "Current database connections"
  query: |
    SELECT 
      count(*) as total,
      count(*) FILTER (WHERE state = 'active') as active,
      count(*) FILTER (WHERE state = 'idle') as idle,
      count(*) FILTER (WHERE state = 'idle in transaction') as idle_in_transaction
    FROM pg_stat_activity
    WHERE pid != pg_backend_pid()
  ttl: 1
  metrics:
    - total: {usage: GAUGE, description: "Total connections"}
    - active: {usage: GAUGE, description: "Active connections"}
    - idle: {usage: GAUGE, description: "Idle connections"}
    - idle_in_transaction: {usage: GAUGE, description: "Idle in transaction"}

Counter with Labels

pg_table_stats:
  desc: "Table statistics"
  query: |
    SELECT 
      schemaname,
      tablename,
      n_tup_ins,
      n_tup_upd,
      n_tup_del,
      n_live_tup,
      n_dead_tup
    FROM pg_stat_user_tables
  ttl: 10
  metrics:
    - schemaname: {usage: LABEL}
    - tablename: {usage: LABEL}
    - n_tup_ins: {usage: COUNTER, description: "Tuples inserted"}
    - n_tup_upd: {usage: COUNTER, description: "Tuples updated"}
    - n_tup_del: {usage: COUNTER, description: "Tuples deleted"}
    - n_live_tup: {usage: GAUGE, description: "Live tuples"}
    - n_dead_tup: {usage: GAUGE, description: "Dead tuples"}

Version-Specific Collector

pg_wal_stats:
  desc: "WAL statistics (PG 14+)"
  min_version: 140000
  query: |
    SELECT 
      wal_records,
      wal_bytes,
      wal_buffers_full,
      wal_write_time,
      wal_sync_time
    FROM pg_stat_wal
  ttl: 10
  tags: [cluster]
  metrics:
    - wal_records: {usage: COUNTER}
    - wal_bytes: {usage: COUNTER}
    - wal_buffers_full: {usage: COUNTER}
    - wal_write_time: {usage: COUNTER, scale: 0.001}
    - wal_sync_time: {usage: COUNTER, scale: 0.001}

Extension-Dependent Collector

pg_stat_statements_metrics:
  desc: "Query performance statistics"
  tags: [extension:pg_stat_statements]
  query: |
    SELECT 
      sum(calls) as total_calls,
      sum(total_exec_time) as total_time,
      sum(mean_exec_time * calls) / sum(calls) as mean_time
    FROM pg_stat_statements
  ttl: 60
  metrics:
    - total_calls: {usage: COUNTER}
    - total_time: {usage: COUNTER, scale: 0.001}
    - mean_time: {usage: GAUGE, scale: 0.001}

Custom Collectors

Creating Your Own Metrics

  1. Create a new YAML file in your config directory:
# /etc/pg_exporter/custom_metrics.yml
app_metrics:
  desc: "Application-specific metrics"
  query: |
    SELECT 
      (SELECT count(*) FROM users WHERE active = true) as active_users,
      (SELECT count(*) FROM orders WHERE created_at > NOW() - '1 hour'::interval) as recent_orders,
      (SELECT avg(processing_time) FROM jobs WHERE completed_at > NOW() - '5 minutes'::interval) as avg_job_time
  ttl: 30
  metrics:
    - active_users: {usage: GAUGE, description: "Currently active users"}
    - recent_orders: {usage: GAUGE, description: "Orders in last hour"}
    - avg_job_time: {usage: GAUGE, description: "Average job processing time"}
  1. Test your collector:
pg_exporter --explain --config=/etc/pg_exporter/

Conditional Metrics

Use predicate queries for conditional metrics:

partition_metrics:
  desc: "Partitioned table metrics"
  predicate_queries:
    - name: "Check if partitioning is used"
      predicate_query: |
        SELECT EXISTS (
          SELECT 1 FROM pg_class 
          WHERE relkind = 'p' LIMIT 1
        )
  query: |
    SELECT 
      parent.relname as parent_table,
      count(*) as partition_count,
      sum(pg_relation_size(child.oid)) as total_size
    FROM pg_inherits
    JOIN pg_class parent ON parent.oid = pg_inherits.inhparent
    JOIN pg_class child ON child.oid = pg_inherits.inhrelid
    WHERE parent.relkind = 'p'
    GROUP BY parent.relname
  ttl: 300
  metrics:
    - parent_table: {usage: LABEL}
    - partition_count: {usage: GAUGE}
    - total_size: {usage: GAUGE}

Performance Optimization

Query Optimization Tips

  1. Use appropriate TTL values:

    • Fast queries: 1-10 seconds
    • Medium queries: 10-60 seconds
    • Expensive queries: 300-3600 seconds
  2. Set realistic timeouts:

    • Default: 100ms
    • Complex queries: 500ms-1s
    • Never disable timeout in production
  3. Use cluster-level tags:

    tags: [cluster]  # Run once per cluster, not per database
  4. Disable expensive collectors:

    pg_table_bloat:
      skip: true  # Disable if not needed

Monitoring Collector Performance

Check collector execution statistics:

# View collector statistics (hit / error / skip counters and durations)
curl http://localhost:9630/stat

# Per-collector duration and error counters, by datname/query
curl -s http://localhost:9630/metrics | grep -E 'pg_exporter_query_scrape_(duration|error_count)'

Troubleshooting Configuration

Validate Configuration

# Dry run - shows parsed configuration
pg_exporter --dry-run

# Explain - shows planned queries
pg_exporter --explain

Common Issues

ProblemSolution
Metrics missingCheck tags and version compatibility
Slow scrapesIncrease TTL, add timeout, disable expensive queries
High memory usageReduce result set size, use LIMIT
Permission errorsVerify query permissions for monitoring user

Debug Logging

Enable debug logging to troubleshoot:

pg_exporter --log.level=debug

4 - API Reference

pg_exporter provides four types of HTTP endpoints: metrics, health checks, traffic routing, and operational management. The default listen port is :9630. The following table lists all endpoints:

EndpointMethodDescription
/metricsGETPrometheus metrics endpoint (path configurable via --web.telemetry-path)
/upGETAliveness check; aliases /health, /liveness, /readiness, /read
/primaryGETPrimary check; aliases /leader, /master, /read-write, /rw
/replicaGETReplica check; aliases /standby, /slave, /read-only, /ro
/reloadGET/POSTHot-reload collector configuration
/explainGETShow per-collector planning decisions
/statGETPer-collector runtime statistics (hits / errors / duration)
/versionGETVersion and build information (plain text)
/GETLanding page linking to the metrics endpoint

Health and routing endpoints return the cached state from background probes: primary, replica, down, starting, or unknown. They do not query the database for each HTTP request. Thus, frequent probes cannot overload the database.


Metrics Endpoint

GET /metrics

This endpoint returns all collected metrics in Prometheus format.

Request

curl http://localhost:9630/metrics

Response

# HELP pg_up last scrape was able to connect to the server: 1 for yes, 0 for no
# TYPE pg_up gauge
pg_up 1

# HELP pg_version server version number
# TYPE pg_version gauge
pg_version 140000

# HELP pg_in_recovery server is in recovery mode? 1 for yes 0 for no
# TYPE pg_in_recovery gauge
pg_in_recovery 0

# HELP pg_exporter_build_info A metric with a constant '1' value labeled with version, revision, branch, goversion, builddate, goos, and goarch from which pg_exporter was built.
# TYPE pg_exporter_build_info gauge
pg_exporter_build_info{version="v1.4.1",branch="main",revision="<git-sha>",builddate="<build-date>",goversion="go1.26.5",goos="linux",goarch="amd64"} 1

# ... additional metrics

Response Format

Metrics follow the Prometheus exposition format:

# HELP <metric_name> <description>
# TYPE <metric_name> <type>
<metric_name>{<label_name>="<label_value>",...} <value> <timestamp>

Self-Monitoring Metrics

In addition to metrics from YAML collectors, /metrics returns the exporter’s runtime metrics. Use --disable-intro to disable the pg_exporter_* metrics. The prefix follows --namespace. In pgBouncer mode, the prefix is pgbouncer_.

MetricLabelsDescription
pg_up—1 when the target database is reachable, 0 otherwise
pg_version—Server version in server_version_num format
pg_in_recovery—1 when in recovery mode (replica)
pg_exporter_build_infoversion, revision, …Constant 1 with build info in labels
pg_exporter_up—Constant 1 while the exporter is alive
pg_exporter_uptime—Seconds since the exporter started
pg_exporter_scrape_total_count / _error_count—Cumulative scrape / failure counts
pg_exporter_scrape_duration—Duration of the last scrape in seconds
pg_exporter_last_scrape_time—Timestamp of the last scrape
pg_exporter_server_scrape_*datnamePer-database scrape duration and success/failure counters
pg_exporter_query_scrape_durationdatname, queryLast execution duration per collector
pg_exporter_query_scrape_total_count / _error_countdatname, queryExecution / failure counts per collector
pg_exporter_query_scrape_hit_count / _metric_countdatname, queryRows returned / metrics emitted per collector
pg_exporter_query_scrape_predicate_skip_countdatname, queryTimes skipped because a predicate returned false
pg_exporter_query_cache_ttldatname, queryResult cache TTL per collector

Use pg_exporter_query_scrape_duration and _error_count to identify slow or failed collectors. These metrics provide a machine-readable equivalent of /stat.


Health Checks

Health endpoints provide multiple ways to monitor PG Exporter and the target database state.

GET /up

This endpoint checks availability from the cached background probe state. It does not probe the database for each HTTP request.

Response Codes

CodeStatusDescription
200OKTarget is available (primary / replica)
503Service UnavailableTarget is unavailable (down / starting / unknown)

Example

# Check whether the service is healthy
curl -I http://localhost:9630/up

HTTP/1.1 200 OK
Content-Type: text/plain; charset=utf-8

GET /health

Alias of /up with identical behavior.

curl http://localhost:9630/health

GET /liveness and GET /readiness

These aliases use the same handler and behavior as /up. Use them for Kubernetes probes:

livenessProbe:
  httpGet: { path: /liveness, port: 9630 }
  initialDelaySeconds: 30
  periodSeconds: 10
readinessProbe:
  httpGet: { path: /readiness, port: 9630 }
  initialDelaySeconds: 5
  periodSeconds: 5

Both endpoints return 503 when the target database is unreachable. To prevent a database failure from restarting the exporter Pod, use a TCP liveness probe on the listen port.


Traffic Routing

Load balancers and proxies use these endpoints to route traffic by server role.

GET /primary

Check whether the server is a primary instance.

Response Codes

CodeStatusDescription
200OKServer is primary and accepting writes
404Not FoundServer is not primary and is acting as a replica
503Service UnavailableServer is unavailable (down / starting / unknown)

Aliases

  • /leader
  • /master
  • /read-write
  • /rw

Example

# Check whether the server is primary
curl -I http://localhost:9630/primary

# Use in HAProxy
backend pg_primary
  option httpchk GET /primary
  server pg1 10.0.0.1:5432 check port 9630
  server pg2 10.0.0.2:5432 check port 9630

GET /replica

Check whether the server is a replica instance.

Response Codes

CodeStatusDescription
200OKServer is a replica and in recovery
404Not FoundServer is not a replica and is acting as primary
503Service UnavailableServer is unavailable (down / starting / unknown)

Aliases

  • /standby
  • /read-only
  • /ro

/slave remains compatible, but /replica is the preferred name.

Example

# Check whether the server is a replica
curl -I http://localhost:9630/replica

# Use in a load balancer
backend pg_replicas
  option httpchk GET /replica
  server pg2 10.0.0.2:5432 check port 9630
  server pg3 10.0.0.3:5432 check port 9630

GET /read

Check whether the server can handle read traffic. Both primaries and replicas may return success.

Response Codes

CodeStatusDescription
200OKServer is healthy and can handle reads
503Service UnavailableServer is unavailable (down / starting / unknown)

Example

# Check whether the server can serve reads
curl -I http://localhost:9630/read

# Route reads to any healthy server
backend pg_read
  option httpchk GET /read
  server pg1 10.0.0.1:5432 check port 9630
  server pg2 10.0.0.2:5432 check port 9630
  server pg3 10.0.0.3:5432 check port 9630

Operational Endpoints

GET /reload / POST /reload

Reload configuration without restarting the exporter.

Request

# POST is recommended
curl -X POST http://localhost:9630/reload

# GET remains supported for compatibility
curl http://localhost:9630/reload

Response

server reloaded

Response Codes

CodeStatusDescription
200OKReload completed successfully
500Internal Server ErrorReload failed and returns fail to reload: ...
405Method Not AllowedNon-GET/POST request, with Allow: GET, POST

Use Cases

  • Update collector definitions
  • Change query parameters
  • Modify cache TTL values
  • Add or remove collectors
Note

Reload updates collector configuration and query plans. To change process settings, such as listen addresses or CLI arguments, restart the exporter.

Security Advice

/reload, /explain, and /stat are management endpoints. If the exporter is reachable outside localhost or a trusted private network, protect these endpoints. Use --web.config.file, or restrict access through a reverse proxy or firewall.

GET /explain

Display planned collector execution details for all configured collectors.

Request

curl http://localhost:9630/explain

Response

##
# SYNOPSIS
#       pg.pg_primary_only_*
#
# DESCRIPTION
#       PostgreSQL basic information (on primary)
#
# OPTIONS
#       Tags       [cluster, primary]
#       TTL        1
#       Priority   110
#       Timeout    100ms
#       Fatal      true
#       Version    100000 ~ higher
#       Source     pg_exporter.yml

...

GET /stat

Show runtime statistics, including collector execution times and success/error counters.

Request

curl http://localhost:9630/stat

Response

name                     total      hit        error      skip       metric     ttl/s  duration/ms
pg                       12         0          0          0          15         1      4.231000
pg_db                    12         11         0          0          28         10     0.153000
pg_activity              12         0          1          0          8          0      7.842000
...

Use this endpoint to identify slow or failed collectors.


Using with Load Balancers

HAProxy Example

# Primary backend for write traffic
backend pg_primary
  mode tcp
  option httpchk GET /primary
  http-check expect status 200
  server pg1 10.0.0.1:5432 check port 9630 inter 3000 fall 2 rise 2
  server pg2 10.0.0.2:5432 check port 9630 inter 3000 fall 2 rise 2 backup

# Replica backend for read traffic
backend pg_replicas
  mode tcp
  balance roundrobin
  option httpchk GET /replica
  http-check expect status 200
  server pg2 10.0.0.2:5432 check port 9630 inter 3000 fall 2 rise 2
  server pg3 10.0.0.3:5432 check port 9630 inter 3000 fall 2 rise 2

# Read backend for any server that can handle reads
backend pg_read
  mode tcp
  balance leastconn
  option httpchk GET /read
  http-check expect status 200
  server pg1 10.0.0.1:5432 check port 9630 inter 3000 fall 2 rise 2
  server pg2 10.0.0.2:5432 check port 9630 inter 3000 fall 2 rise 2
  server pg3 10.0.0.3:5432 check port 9630 inter 3000 fall 2 rise 2

A Note on Nginx

Open-source Nginx does not support active HTTP health checks outside the traffic connection. The health_check directive requires NGINX Plus. PostgreSQL traffic also requires the stream module instead of http proxying. To route PostgreSQL traffic by role, use HAProxy as shown above, or a solution such as Patroni + vip-manager.

5 - Deployment

Production deployment — connection & credentials, systemd / Docker / Kubernetes, auto-discovery and alerting

Use this page to deploy pg_exporter in production. It describes process arguments, environment variables, monitoring users, credentials, and deployment with systemd, Docker, or Kubernetes. It also describes pgBouncer monitoring, auto-discovery, Prometheus scrapes, and alerts.

The exporter reads process configuration from two sources. Command-line arguments take precedence:

  1. Command-line arguments (--url, --config, …)
  2. Environment variables (every flag has a corresponding PG_EXPORTER_* variable)

YAML collector definitions control metric collection. The default file is /etc/pg_exporter.yml. You can also use a configuration directory. See the Configuration reference.


Command-Line Arguments

pg_exporter \
  --url="postgres://monitor:S3cret@localhost:5432/postgres" \
  --config="/etc/pg_exporter.yml" \
  --web.listen-address=":9630" \
  --auto-discovery \
  --log.level="info"

The full flag list from pg_exporter --help:

Flags:
  -h, --[no-]help                Show context-sensitive help (also try --help-long and --help-man).
  -u, --url=URL                  postgres target url
  -c, --config=CONFIG            path to config dir or file
      --web.listen-address=:9630 ...
                                 Addresses on which to expose metrics and web interface. Repeatable for multiple addresses. Examples: `:9100` or `[::1]:9100` for http, `vsock://:9100` for vsock
      --web.config.file=""       Path to configuration file that can enable TLS or authentication. See: https://github.com/prometheus/exporter-toolkit/blob/master/docs/web-configuration.md
  -l, --label=""                 constant labels: comma separated list of label=value pair ($PG_EXPORTER_LABEL)
  -t, --tag=""                   tags, comma separated list of server tag ($PG_EXPORTER_TAG)
  -C, --[no-]disable-cache       force not using cache ($PG_EXPORTER_DISABLE_CACHE)
  -m, --[no-]disable-intro       disable internal/exporter self-monitoring metrics (only expose query metrics) ($PG_EXPORTER_DISABLE_INTRO)
  -a, --[no-]auto-discovery      automatically scrape all databases on the target server ($PG_EXPORTER_AUTO_DISCOVERY)
  -x, --exclude-database="template0,template1,postgres"
                                 excluded databases when auto-discovery is enabled ($PG_EXPORTER_EXCLUDE_DATABASE)
  -i, --include-database=""      included databases when auto-discovery is enabled ($PG_EXPORTER_INCLUDE_DATABASE)
  -n, --namespace=""             prefix of built-in metrics, (pg|pgbouncer) by default ($PG_EXPORTER_NAMESPACE)
  -f, --[no-]fail-fast           fail fast instead of waiting during start-up ($PG_EXPORTER_FAIL_FAST)
  -T, --connect-timeout=100      connect timeout in ms, 100 by default ($PG_EXPORTER_CONNECT_TIMEOUT)
  -P, --web.telemetry-path="/metrics"
                                 URL path under which to expose metrics ($PG_EXPORTER_TELEMETRY_PATH)
  -D, --[no-]dry-run             dry run and print raw configs
  -E, --[no-]explain             explain server planned queries
      --log.level="info"         log level: debug|info|warn|error
      --log.format="logfmt"      log format: logfmt|json
      --[no-]version             Show application version.

These behaviors affect deployment:

  • Startup policy: startup is non-blocking by default. If the database is unreachable, HTTP endpoints still start. A background probe retries until recovery. To fail when the database is unreachable, set --fail-fast. For example, use this option when systemd or an orchestrator controls restarts.
  • Telemetry path validation: from v1.4.0, startup validates --web.telemetry-path. Empty paths, conflicts with built-in endpoints, and non-canonical paths such as //metrics fail immediately with an error. Non-canonical paths cannot match requests.

Connection URL Sources

The exporter uses the first non-empty connection string from this list:

  1. --url / -u command-line argument
  2. PG_EXPORTER_URL environment variable
  3. PGURL environment variable
  4. Content of the file pointed to by PG_EXPORTER_URL_FILE (fits container Secret mounts)
  5. Default postgresql:///?sslmode=disable (local-first, fits same-host deployment)

If the URL omits sslmode, the exporter appends sslmode=disable. At startup, it also clears libpq service-file environment variables, such as PGSERVICE / PGSERVICEFILE, and logs this action. Service files can override an explicit connection target. Clearing these variables ensures that the exporter connects to the URL shown in the log.


Monitoring User and Credentials

Create the Monitoring User

CREATE ROLE monitor WITH LOGIN PASSWORD 'S3cret' CONNECTION LIMIT 5;
GRANT pg_monitor TO monitor;   -- built-in monitoring role (PostgreSQL 10+), covers all default collectors

Keep CONNECTION LIMIT to prevent connection exhaustion if the configuration is incorrect. The exporter normally uses one to a few connections. With auto-discovery, it uses one connection per database.

Manage Passwords with .pgpass

Remove the password from the URL. Use libpq’s .pgpass file to supply it:

# Create as the OS user that runs the exporter
echo "localhost:5432:*:monitor:S3cret" > ~/.pgpass
chmod 600 ~/.pgpass

# URL without password
PG_EXPORTER_URL='postgres://monitor@localhost:5432/postgres'
RPM/DEB package installs

Packaged services run as the prometheus system user. From v1.4.0, its HOME is /var/lib/prometheus. Libpq looks for ~/.pgpass there. The package does not create this directory. Before you use .pgpass, run: install -d -o prometheus -g prometheus /var/lib/prometheus

TLS for the Database Connection

PG_EXPORTER_URL='postgres://monitor:[email protected]:5432/postgres?sslmode=verify-full&sslrootcert=/etc/pki/ca.crt'

Protecting the HTTP Port

The HTTP port provides /metrics and the management endpoints /reload, /explain, and /stat. Anyone with access to the port can read configuration and runtime state, or start a reload. On a shared network, enable TLS / Basic Auth with --web.config.file (exporter-toolkit web configuration). You can also restrict access through a firewall or reverse proxy.


Systemd Deployment (RPM/DEB packages)

RPM/DEB packages include a service unit and an environment file. After installation, edit the environment file and start the service:

# /usr/lib/systemd/system/pg_exporter.service
[Unit]
Description=Prometheus exporter for PostgreSQL/Pgbouncer server metrics
Documentation=https://pigsty.io/docs/pg_exporter
After=network.target

[Service]
EnvironmentFile=-/etc/default/pg_exporter
User=prometheus
ExecStart=/usr/bin/pg_exporter $PG_EXPORTER_OPTS
Restart=on-failure

[Install]
WantedBy=multi-user.target

Environment file /etc/default/pg_exporter (package defaults):

PG_EXPORTER_URL='postgres://:5432/postgres?sslmode=disable'
PG_EXPORTER_CONFIG=/etc/pg_exporter.yml
PG_EXPORTER_LABEL=""
PG_EXPORTER_TAG=""
PG_EXPORTER_DISABLE_CACHE=false
PG_EXPORTER_AUTO_DISCOVERY=true
PG_EXPORTER_EXCLUDE_DATABASE="template0,template1,postgres"
PG_EXPORTER_INCLUDE_DATABASE=""
PG_EXPORTER_NAMESPACE="pg"
PG_EXPORTER_FAIL_FAST=false
PG_EXPORTER_CONNECT_TIMEOUT=100
PG_EXPORTER_TELEMETRY_PATH="/metrics"
PG_EXPORTER_OPTS='--log.level=info'

Each command-line flag has an environment variable. Add the variables you need, such as PG_EXPORTER_DISABLE_INTRO. The file uses the noreplace package option. Upgrades do not overwrite your changes.

Common operations:

sudo systemctl enable --now pg_exporter    # start and enable at boot
sudo systemctl status pg_exporter          # check status
journalctl -u pg_exporter -f               # follow logs
curl -X POST localhost:9630/reload         # hot-reload collector config (no restart)

Docker Deployment

docker run -d \
  --name pg_exporter \
  --restart unless-stopped \
  -p 9630:9630 \
  -e PG_EXPORTER_URL="postgres://monitor:S3cret@host:5432/postgres" \
  pgsty/pg_exporter:latest

Docker Compose:

services:
  pg_exporter:
    image: pgsty/pg_exporter:latest
    container_name: pg_exporter
    restart: unless-stopped
    ports:
      - "9630:9630"
    environment:
      - PG_EXPORTER_URL=postgres://monitor:S3cret@postgres:5432/postgres
    volumes:
      - ./pg_exporter.yml:/etc/pg_exporter.yml:ro   # optional: custom collector config
    depends_on:
      - postgres
Note

The official image is built from scratch. It contains no system CA certificates. To connect to remote PostgreSQL with sslmode=verify-ca / verify-full, mount a CA certificate and set sslrootcert to its path. Without the certificate, TLS verification cannot complete.


Kubernetes Deployment

apiVersion: apps/v1
kind: Deployment
metadata:
  name: pg-exporter
  labels: { app: pg-exporter }
spec:
  replicas: 1
  selector:
    matchLabels: { app: pg-exporter }
  template:
    metadata:
      labels: { app: pg-exporter }
    spec:
      containers:
      - name: pg-exporter
        image: pgsty/pg_exporter:latest
        ports:
        - containerPort: 9630
        env:
        - name: PG_EXPORTER_URL
          valueFrom:
            secretKeyRef:
              name: pg-credentials
              key: connection-url
        livenessProbe:
          httpGet: { path: /liveness, port: 9630 }
          initialDelaySeconds: 30
          periodSeconds: 10
        readinessProbe:
          httpGet: { path: /readiness, port: 9630 }
          initialDelaySeconds: 5
          periodSeconds: 5
        resources:
          requests: { cpu: 100m, memory: 128Mi }
          limits: { cpu: 200m, memory: 256Mi }
---
apiVersion: v1
kind: Service
metadata:
  name: pg-exporter
  labels: { app: pg-exporter }
spec:
  ports:
  - { port: 9630, targetPort: 9630, name: metrics }
  selector: { app: pg-exporter }

To keep the connection string out of environment variables, set PG_EXPORTER_URL_FILE to a Secret-mounted file.


Auto-Discovery

Auto-discovery is enabled by default. It lets one exporter instance monitor every database in the target PostgreSQL instance:

pg_exporter --auto-discovery \
  --exclude-database="template0,template1,postgres" \  # default exclusion list
  --include-database=""                                # set to switch to allowlist mode

Behavior:

  • Cluster-level collectors (tags: [cluster]) run once on the primary connection
  • Database-level collectors run on every discovered database, with metrics distinguished by the datname label
  • Newly created / dropped databases are picked up / removed in subsequent planning cycles

Monitoring pgBouncer

Set the database name in the URL to pgbouncer. This name activates pgBouncer mode:

PG_EXPORTER_URL='postgres://stats_user:S3cret@localhost:6432/pgbouncer' pg_exporter

In pgBouncer mode, the exporter uses the pgbouncer metric prefix. It runs only pgBouncer collectors, such as SHOW STATS / SHOW POOLS. Usually, you run one exporter for PostgreSQL and another for pgBouncer. Give each exporter a different port.


Prometheus Scraping and Alerting

Scrape Configuration

scrape_configs:
  - job_name: 'postgresql'
    scrape_interval: 15s
    static_configs:
      - targets: ['pg-1:9630', 'pg-2:9630', 'pg-3:9630']

Kubernetes service discovery:

scrape_configs:
  - job_name: 'postgresql'
    kubernetes_sd_configs:
      - role: pod
    relabel_configs:
      - source_labels: [__meta_kubernetes_pod_label_app]
        regex: pg-exporter
        action: keep
      - source_labels: [__meta_kubernetes_pod_ip]
        target_label: __address__
        replacement: ${1}:9630

Set the scrape interval equal to or greater than the common collector ttl. Most collectors in the default bundle use 10 seconds. More frequent scrapes return cached results until the TTL expires.

Alert Rules

The following rules use available metrics:

groups:
  - name: pg_exporter
    rules:
      # Exporter process unreachable
      - alert: PgExporterDown
        expr: up{job="postgresql"} == 0
        for: 1m
        labels: { severity: critical }
        annotations:
          summary: "pg_exporter down ({{ $labels.instance }})"

      # Exporter alive but cannot reach the database
      - alert: PostgreSQLDown
        expr: pg_up == 0
        for: 1m
        labels: { severity: critical }
        annotations:
          summary: "PostgreSQL connection failed ({{ $labels.instance }})"

      # Overall scrape duration abnormal (unit: seconds)
      - alert: PgExporterSlowScrape
        expr: pg_exporter_scrape_duration > 10
        for: 5m
        labels: { severity: warning }
        annotations:
          summary: "pg_exporter slow scrape ({{ $labels.instance }})"

      # A specific collector keeps failing (locate by datname/query)
      - alert: PgExporterQueryError
        expr: increase(pg_exporter_query_scrape_error_count[10m]) > 0
        for: 10m
        labels: { severity: warning }
        annotations:
          summary: "Collector {{ $labels.query }} keeps failing on {{ $labels.datname }}"

Role-Based Traffic Routing

Use /primary, /replica, and /read as health probes for HAProxy or similar load balancers. These endpoints support primary/replica routing to separate read and write traffic. For endpoint behavior and a complete HAProxy example, see the API Reference.

Open-source Nginx does not support active HTTP health checks outside the traffic connection. The health_check directive requires NGINX Plus. To route PostgreSQL traffic by role, use HAProxy or a solution such as Patroni + vip-manager.

6 - Release Notes

The latest stable version of pg_exporter is v1.4.1

VersionDateSummaryGitHub
v1.4.12026-07-29Subscription count and label validation fixes; RPM renamev1.4.1
v1.4.02026-07-18Snapshot histograms, pg_xact_age collector, HTTP hardeningv1.4.0
v1.3.02026-06-24PostgreSQL 19 support, new PG19 collectors and branchesv1.3.0
v1.2.22026-04-14Routine Go 1.26.2 refresh, no functional changesv1.2.2
v1.2.12026-03-21Config style cleanup, Go 1.26.1 refreshv1.2.1
v1.2.02026-02-12Hot reload, non-blocking startup, PG9.x legacy supportv1.2.0
v1.1.22026-01-16fix pg_timeline conf issue, build with latest depsv1.1.2
v1.1.12025-12-30New pg_timeline collector, pg_sub_16 branch, bug fixesv1.1.1
v1.1.02025-12-15Update default metrics collectors, bump to go 1.25.5v1.1.0
v1.0.32025-11-20Routine update on 1.25.4, fix unsupported libpq envv1.0.3
v1.0.22025-08-14Build for more os arch with goreleaserv1.0.2
v1.0.12025-07-17DockerHub images, Go 1.24.5, disable pg_tsdb_hypertablev1.0.1
v1.0.02025-05-06PostgreSQL 18 support, new WAL/checkpointer/I/O metricsv1.0.0
v0.9.02025-04-26TimescaleDB, Citus, pg_wait_sampling collectorsv0.9.0
v0.8.12025-02-14Dependencies update, docker image tagsv0.8.1
v0.8.02025-02-14PgBouncer 1.24 support, Go 1.24, logging refactorv0.8.0
v0.7.12024-12-29Routine update, configuration as Reader supportv0.7.1
v0.7.02024-08-13PostgreSQL 17 support, predicate queries featurev0.7.0
v0.6.02023-10-18PostgreSQL 16 support, ARM64 packages, security fixesv0.6.0
v0.5.02022-04-27RPM/DEB builds, column scaling, metrics enhancementsv0.5.0
v0.4.12022-03-08Collector updates, connect-timeout parameterv0.4.1
v0.4.02021-07-12PostgreSQL 14 support, auto-discovery featurev0.4.0
v0.3.22021-02-01Shadow DSN fixes, documentation updatesv0.3.2
v0.3.12020-12-04Configuration fixes for older PostgreSQL versionsv0.3.1
v0.3.02020-10-29PostgreSQL 13 support, REST APIs, dummy serverv0.3.0
v0.2.02020-03-21YUM packages, configuration reload supportv0.2.0
v0.1.22020-02-20Dynamic configuration reload, bulky modev0.1.2
v0.1.12020-01-10Startup hang bug fixv0.1.1
v0.1.02020-01-08Initial stable releasev0.1.0
v0.0.42019-12-20Production tested releasev0.0.4
v0.0.32019-12-14Production environment testingv0.0.3
v0.0.22019-12-09Early testing releasev0.0.2
v0.0.12019-12-06Initial release with PgBouncer modev0.0.1

v1.4.1

v1.4.1 is a maintenance release focused on metric accuracy and RPM upgrade compatibility.

Highlights:

  • Fix pg_subrel_count overcounting with parallel logical replication apply workers. Deduplicate pg_stat_subscription by subscription ID and name before aggregating subscription relation states.
  • If a query result omits a configured LABEL column, fail the entire collector scrape. Do not emit an empty label or keep stale results. Other non-fatal collectors continue normally.
  • Rename the official RPM package and artifact prefix from pg_exporter to pg-exporter. The new package provides and obsoletes the legacy name to support direct upgrades.
  • Update version and standalone package metadata. Add regression tests for missing labels. Validate RPM configuration, artifact names, and compatibility metadata in CI.

Upgrade Notes:

  • Custom collector SQL must return every LABEL column. The result schema must be complete even if the query returns zero rows.
  • If automation matches GitHub RPM file names directly, change pg_exporter-*.rpm to pg-exporter-*.rpm.

https://github.com/pgsty/pg_exporter/releases/tag/v1.4.1

v1.4.0

v1.4.0 adds Snapshot Histogram metrics and the pg_xact_age transaction age collector. It also improves HTTP routing, packaging, and the build toolchain.

New Features:

  • Add the HISTOGRAM column type. It aggregates SQL snapshots by label group into classic Prometheus histograms with _bucket / _count / _sum series. Configuration loading validates finite bucket bounds in strictly increasing order and appends +Inf automatically. The le label is reserved. Hot reload is supported.
  • Add the pg_xact_age collector. It returns open transaction age (pg_xact_age_seconds) and idle-in-transaction age (pg_xact_age_idle_seconds) as histograms. It collects cluster-level data from client backends only, with a 10s TTL.
  • Increase the default bundle from 57 to 58 definition files. Assign pg_xact_age to slot 0450. Renumber pg_lock / pg_lock_stat / pg_query to 0460 / 0470 / 0480 without content changes.

Fixes & Improvements:

  • Register HTTP routes in a private ServeMux instead of the global DefaultServeMux. This prevents accidental exposure of endpoints from third-party libraries.
  • Validate --web.telemetry-path at startup. Reject empty paths, paths without a leading /, paths with ? # { }, and conflicts with built-in endpoints. Also reject non-canonical paths such as //metrics, which cannot match requests. Each failure returns a clear error immediately.
  • Escape the telemetry path in the landing page HTML.
  • Close the primary connection pool if the --fail-fast pre-check fails.
  • Fix RPM / DEB packaging (#105). Set the prometheus user’s HOME to /var/lib/prometheus, where libpq looks for ~/.pgpass. Add /postgres to the packaged default URL. This prevents libpq from using a database named after the OS user.
  • Use the v version prefix consistently. Official release binaries report v1.4.0 in --version, /version, and pg_exporter_build_info{version=...}. GoReleaser artifacts previously reported 1.3.0 without the prefix. Artifact file names, package versions, and Docker image tag conventions do not change.
  • Apply the same value conversion rules to histograms and scalar columns. Exclude timestamps and booleans from scale.
  • Correct GoReleaser package metadata to show support for PostgreSQL 9.x - 19+ and pgBouncer 1.8 - 1.25+.
  • Restore GOPROXY / GOSUMDB build-argument passthrough in make docker.

Engineering & Build:

  • Update the build toolchain to Go 1.26.5, exporter-toolkit v0.17.1, and prometheus/common v0.70.0.
  • Add regular CI checks for module tidy, generated configuration, race tests, and six-platform cross-builds. The make conf output must match config/*.yml.
  • Remove the docker/ scripts and make docker-release. Use GoReleaser to build multi-architecture release images.
  • Remove assumptions about specific collectors from configuration coverage tests. This makes smaller custom bundles easier to maintain.

Upgrade Notes:

  • A non-canonical telemetry path, such as //metrics, now prevents startup. Previously, the process started but the metrics endpoint was unreachable.
  • Update automation that parses the version label of pg_exporter_build_info or the --version output to accept the v prefix.
  • If any collector uses HISTOGRAM, do not use le as a constant label.

Checksums

https://github.com/pgsty/pg_exporter/releases/download/v1.4.0/checksums.txt

9874191591567ede87ae1d5820f06e781f27c664a7f4a6365211f9e042fd8199  checksums.txt
c6af4ae62e13f518539a6d0b3ce86ff9f7acdb567a4f0f86c6f47563574da724  pg-exporter_1.4.0-1_amd64.deb
ff0360f61982ed627d1b1f93281a0ba66da9d077672f0c214e19522df01e40d6  pg-exporter_1.4.0-1_arm64.deb
4fbadd4e9d918c9bc8e63975378e49375b0ff897d6b8a0f78799538b13dd68a1  pg-exporter_1.4.0-1_ppc64le.deb
5ce106d27fffa77c39fea9bf7cbc60f4328df3d926fef025bfdd082eb6d743fd  pg_exporter-1.4.0-1.aarch64.rpm
870b434e802e0039f10e1e3583c28a1fd83db4363a4608e1fab7f375f6d30600  pg_exporter-1.4.0-1.ppc64le.rpm
c550d16ce3f9276948a4d44174e11716fc5e85e31e8788ea106a57cfbabd8488  pg_exporter-1.4.0-1.x86_64.rpm
11a34e531ac5d6d378b91e768f575525389141a6860afabd0cc9f2d853f06749  pg_exporter-1.4.0.darwin-amd64.tar.gz
49d8d3a5932602f433c4ef681ed12007da1cbc11b5ee0f9d7b4dc2d0dff8e26e  pg_exporter-1.4.0.darwin-arm64.tar.gz
113dfe70d4f780a456c05ca6b731f96c1013bf35ecb87d75c443fe2bac7e333b  pg_exporter-1.4.0.linux-amd64.tar.gz
68b4630ab39943658a8aff135990896a5ccf56c8a992e5982d572c78ef822e18  pg_exporter-1.4.0.linux-arm64.tar.gz
72710625e5658c941b48f7becba9a86491852cea5469240328292838d9ed0979  pg_exporter-1.4.0.linux-ppc64le.tar.gz
14a0cf6ffa04c7e54c1d5aa5b37fe4bea1429c1d1e7cce89e9dd805c4a29db0b  pg_exporter-1.4.0.windows-amd64.tar.gz

https://github.com/pgsty/pg_exporter/releases/tag/v1.4.0


v1.3.0

v1.3.0 adds PostgreSQL 19 support. It also updates the default collectors, build toolchain, and configuration coverage tests.

Highlights:

  • Default support range extended from PostgreSQL 10-18+ to 10-19+
  • Default config bundle includes 57 config/*.yml definition files
  • Build dependencies updated to Go 1.26.4, lib/pq v1.12.3, Prometheus client v1.23.2, and exporter-toolkit v0.16.0
  • pg_recovery_state: collect pg_stat_recovery on recovery nodes, exposing promotion trigger status, replay LSN, timeline, recovery transaction time, and pause state
  • pg_lock_stat: collect PG19 pg_stat_lock, exposing waits, wait time, and fast-path overflow counts by locktype
  • pg_vacuum_score: collect the current-database summary from pg_stat_autovacuum_scores, exposing max autovacuum score and candidate table count
  • pg_wal_19: expose wal_fpi_bytes on PG19 as pg_wal_fpi_bytes
  • pg_sub_19: adapt sequence sync and logical replication conflict stats from pg_stat_subscription_stats, while keeping sync_error_count for legacy dashboards
  • pg_recv: recognize the PG13+ WAL receiver connecting state on PG19
  • pg_slot: recognize the PG19 replication slot invalidation reason idle_timeout
  • pg_db_confl: switch to an explicit column list to avoid accidentally exporting future view columns
  • pg_backup, pg_vacuuming, and pg_clustering continue reusing stable existing branches instead of changing the metric surface for low-value PG19 fields

Checksums

https://github.com/pgsty/pg_exporter/releases/download/v1.3.0/checksums.txt

c88c4ad7cde10531d75ec98fa536b2e7f531639f55c3b3c9866ee76934a4e2b2  checksums.txt
dfc6d517300687a382557e6d77af1ecb513bdde2e961d01ca46efa008ae15569  pg-exporter_1.3.0-1_amd64.deb
3d2ff642d0bb3657b28eb7c4b30bacc8ef9e4cbd057c870e6ec6817b47ac8092  pg-exporter_1.3.0-1_arm64.deb
4cfe043eb193780515a1e00ab93250dd44ca0728b35cb037ed165c70c89b6b5a  pg-exporter_1.3.0-1_ppc64le.deb
3ae4f8c554242ae52c4ba0fa07a9d95b702f72938ce55e8456dd97242cc46faf  pg_exporter-1.3.0-1.aarch64.rpm
71a0023383170b4ef3c243d9bf08d530b819fa891fa784e87c74b2a55cb426ec  pg_exporter-1.3.0-1.ppc64le.rpm
316a97ccb2df9a02de99dda33826857ec32bbd6fd874ffb950625bc064d62496  pg_exporter-1.3.0-1.x86_64.rpm
4ab312f27f0ded7f0ff5591866a86311d13041fef3a015e92f44fcf4a2284ccd  pg_exporter-1.3.0.darwin-amd64.tar.gz
2b20eb7b46c0790a8524f1c00a22ab57739bd60fd89ee947f6c2ba14e6a0d6bb  pg_exporter-1.3.0.darwin-arm64.tar.gz
7a2a8ce818f30260d1e7267d0b9e1fd5b3cbd569d55ad184fc9d6fb3801f3ad7  pg_exporter-1.3.0.linux-amd64.tar.gz
696619d19efbcf33f4afbae9748e72897289d2b7f772509cd6d465c9e818066d  pg_exporter-1.3.0.linux-arm64.tar.gz
0c16ac4a912f328be90e973b5123a272c2747759be9f56bacb5542653226475e  pg_exporter-1.3.0.linux-ppc64le.tar.gz
aa3724f4e8aeb732de18b7cb416283cbc2e94b9f511ec4b94e703792e8e8b10d  pg_exporter-1.3.0.windows-amd64.tar.gz

https://github.com/pgsty/pg_exporter/releases/tag/v1.3.0

v1.2.2

v1.2.2 updates the release toolchain to Go 1.26.2. This maintenance release has no changes to collectors, configuration behavior, or runtime behavior.

Highlights

  • Refresh the release toolchain: bump release builds to Go 1.26.2
  • No functional changes: collector behavior, default configs, metric definitions, and runtime semantics remain unchanged

Checksums

https://github.com/pgsty/pg_exporter/releases/download/v1.2.2/checksums.txt

273dfd45ac367f71044998d19171ee27d7deb094ec9410d4b31aef7caacfdcc6  pg-exporter_1.2.2-1_amd64.deb
5e83c8448ee6350bec96ab95550df439a129c6700e5c9c7d0f9411aa9c2e7f40  pg-exporter_1.2.2-1_arm64.deb
97bb804bd1018c111708df9118561421d2cc51bd47d031b6d1f12cf1c988a3b2  pg-exporter_1.2.2-1_ppc64le.deb
b2f76799b21aba02b6bf5b6e71bf7ae2cf4487ad8817d53aad92f1d710c00120  pg_exporter-1.2.2-1.aarch64.rpm
f0ab38907bc87a9634c22911d8a0501634d58ce34020c0952dd49281a06787e6  pg_exporter-1.2.2-1.ppc64le.rpm
2000593d9d6732f3e03a43e291bc4e2368d2ecea125a2744dc533a030f51c800  pg_exporter-1.2.2-1.x86_64.rpm
e8a71704eb6957beaebd8ecaf83479e44db4a09bd9dc95c32f7b617f141b0386  pg_exporter-1.2.2.darwin-amd64.tar.gz
e648d9444f9a5f3ee49b82bcbbb459eefd73307c789f24f0d5238dbe1bcfec9c  pg_exporter-1.2.2.darwin-arm64.tar.gz
f278aba93d09b2a47aeef66898e770cacfdbc046eab0ba02de29f7c0261d9ede  pg_exporter-1.2.2.linux-amd64.tar.gz
bbeef56452643b8eb6bf9bb5baf113ab2c38177c06f8e1d008e63cce82260801  pg_exporter-1.2.2.linux-arm64.tar.gz
ad2385278ec6060fef2f7db7873c025f56f5c55048b51815cb4195486ca9dbe2  pg_exporter-1.2.2.linux-ppc64le.tar.gz
2ac53298058f09c5569464f918396f13d3a9efebec00296d89497e97ea74caf4  pg_exporter-1.2.2.windows-amd64.tar.gz

https://github.com/pgsty/pg_exporter/releases/tag/v1.2.2

v1.2.1

v1.2.1 is a maintenance release for release engineering, configuration package consistency, documentation, and metadata. It has no changes to collector or runtime behavior.

Highlights

  • Refresh the build toolchain: bump both release workflows and Docker build images to Go 1.26.1
  • Standardize config style: switch inline description values in both current and legacy configs to double-quoted form, and regenerate merged pg_exporter.yml / legacy/pg_exporter.yml
  • Add config consistency tests: verify split and merged configs remain equivalent, and check inline metric description style to reduce configuration drift
  • Refresh packaging metadata: update RPM / DEB support descriptions to PostgreSQL 9.x - 18+ and pgBouncer 1.8 - 1.25+, and refresh Pigsty documentation links

Checksums

2cbe7a78a0dde8a6155a543232af883de6623531c9f6ea0951ddc30dc7514649  pg-exporter_1.2.1-1_amd64.deb
e70e09974ad52ba607b176b63c300610e37f44fe67d249aa9ef364bd58352585  pg-exporter_1.2.1-1_arm64.deb
4e6c7fae85e7fe2e62c3d66c388b5f3db57b5e95e85f43ce648d21b792d83d87  pg-exporter_1.2.1-1_ppc64le.deb
30103629e8c5c1ee5589addadb37fcb07b43179c8a19f80c016a0ed8d7ac2a47  pg_exporter-1.2.1-1.aarch64.rpm
01b4dd32b20bca8612f71f0edf3557dfa92fc85f669d3260f627d34ce102b517  pg_exporter-1.2.1-1.ppc64le.rpm
5afb4f14aa71b256cdfc93d6cc6da8a7052427d6f1c1b71900bf2593b196de50  pg_exporter-1.2.1-1.x86_64.rpm
45e71c6017beffabf2873841d374b5de40eb499dd768d6db1208d7cc6295bcf5  pg_exporter-1.2.1.darwin-amd64.tar.gz
d3035cc6a023fe1bad5443a7c1d5c8189b3d807d165f131f88566b5c35476259  pg_exporter-1.2.1.darwin-arm64.tar.gz
14d3f83de4377e5363611d2ae4eef9470a85d7518784c06b8a8c0f63b6e0a340  pg_exporter-1.2.1.linux-amd64.tar.gz
71082081e7aaf1cf15c941c310d03da49cf9971205274aad7dae21a126bc4fe1  pg_exporter-1.2.1.linux-arm64.tar.gz
cba30919b8d2945be199a4a346eb2891c88fd7a1d6c3482c1006442f4f6109e7  pg_exporter-1.2.1.linux-ppc64le.tar.gz
6fe528a242f0bbd3b89cd8b2697f48905b5c4b1398abfb3305193808c01738e9  pg_exporter-1.2.1.windows-amd64.tar.gz

https://github.com/pgsty/pg_exporter/releases/tag/v1.2.1

v1.2.0

v1.2.0 improves stability and compatibility for startup, hot reload, health probes, configuration validation, and legacy support.

New Features:

  • Improve hot reload. Support platform-specific signals (SIGHUP / SIGUSR1) and improve POST /reload to update configuration and query plans without a restart.
  • Use non-blocking startup. HTTP endpoints start even if the target precheck fails. This improves recovery and monitoring integration.
  • Add a legacy configuration bundle for PostgreSQL 9.1-9.6. Use legacy/ and the make conf9 target to configure monitoring for EOL versions.
  • Use cached health snapshots with periodic probes. This improves consistency for role-based health endpoints and reloads.
  • Add go test and go vet to release workflows. Update the build toolchain to Go 1.26.0.

Bug Fixes:

  • Fix configuration parsing cases. Reject malformed metric entries, return explicit errors if a configuration directory has no valid YAML, and improve runtime fallbacks.
  • Fix CLI boolean parsing for arguments such as --flag=false.
  • Fix /explain output with corrected content types and safer template rendering.
  • Improve predicate queries and PG URL handling. Improve BOOL/BOOLEAN support, row resource handling, and dbname query-parameter parsing and redaction.
  • Close connections asynchronously when auto-discovery removes a target.
  • Fix metric and label validation. Check constant-label conflicts, scaled default values, and Prometheus naming rules.

Checksums

26e7a052e730b412bbbe5f49846f951b89650f1f95c2466d5d486923f0825f64  pg-exporter_1.2.0-1_amd64.deb
4ec219135c49708d010af7b8a7553b8008f630574e1d4cfc7642fbf951eefafe  pg-exporter_1.2.0-1_arm64.deb
5b2cc00e2c3e2ffd9eb0ab1a4f5e937dd68f3a69a14423a74d4de3d7cf29283e  pg-exporter_1.2.0-1_ppc64le.deb
d536d41a92e8aa85ae3935715d1bf0463208b1e614eae73543f1472ca8a7e0d4  pg_exporter-1.2.0-1.aarch64.rpm
b7a1daa225f8ca4de6d227e6004330589295d924accd221892ebe14f191fe35c  pg_exporter-1.2.0-1.ppc64le.rpm
28bf7d85862510675c64ff5181d216c6a068a23ffa56dc4bb9e6b82165ff99b5  pg_exporter-1.2.0-1.x86_64.rpm
51c3b3d18089d888a54a6b3e7ecb0620dc0da04c81471a0b7aaa88c1677ddb8c  pg_exporter-1.2.0.darwin-amd64.tar.gz
3ba1c7adea9c926afd3054ba18cc43e665e420a495bfcfd2248242c49a67b077  pg_exporter-1.2.0.darwin-arm64.tar.gz
9e1ec6c15e6b2aaadbe27a27053ee1ec289bdd012c19ca6371de738fa5f8843e  pg_exporter-1.2.0.linux-amd64.tar.gz
9e18849693ccda313979db0a230cb81acfe4199364feb6ce3e72d1a89fbfb809  pg_exporter-1.2.0.linux-arm64.tar.gz
6e28489685d0bd1fdabcb71474f64f559ade199b871666954323bae9dc01465f  pg_exporter-1.2.0.linux-ppc64le.tar.gz
9e9beac619fe2c614a77bc3334bc4b80df9db355bf95845eb4b11674ddad52d9  pg_exporter-1.2.0.windows-amd64.tar.gz

https://github.com/pgsty/pg_exporter/releases/tag/v1.2.0

v1.1.2

This minor release fixes the pg_timeline configuration and builds with the latest Go dependencies.

Checksums

https://github.com/pgsty/pg_exporter/releases/download/v1.1.2/checksums.txt

8cddd57a843914a3145a80a3220bc875047b9bcac0664357c01ba86485436236  pg-exporter_1.1.2-1_amd64.deb
f5b25a8ae5c022867a54c17ba1c6493eba20dcb292340460390289336df24f04  pg-exporter_1.1.2-1_arm64.deb
4da2c287f6717681b25befda0d59a89b9d1b258281ce94f3a6bc21d02f70c83c  pg-exporter_1.1.2-1_ppc64le.deb
b26355f3c1a5b8a147291a51e2d7ada204deed6d52877c146a8b3e499defa5e8  pg_exporter-1.1.2-1.aarch64.rpm
42ef89716ba99dd918b0e9c77ef3236129d613f68bb8ae5929668a5a2596cca5  pg_exporter-1.1.2-1.ppc64le.rpm
a8f4a2d5c7b6701c7bac788a7ed7183b6c4b74a334326cd389f3a695fb77675d  pg_exporter-1.1.2-1.x86_64.rpm
775f5ea3188a6acb1327c001c4ba9a0651424c3bb37d800e6f67972c904c4750  pg_exporter-1.1.2.darwin-amd64.tar.gz
7f2bbcc2db1e16dc78c3edd8e67e20e4ec81f2972c8c37135cba6f6afbf91003  pg_exporter-1.1.2.darwin-arm64.tar.gz
33c34b1f9ef6b6e7615f241a95059a8137a2337a454930b668180a9329d12b98  pg_exporter-1.1.2.linux-amd64.tar.gz
2b91a5818d780e38692ab6446cacb496695e67388676c18012be582e8ddfbdd8  pg_exporter-1.1.2.linux-arm64.tar.gz
adcb5f229f4a5d641f6430b9a2dfb0377a2e4310efad242730867d6cdf5e27ee  pg_exporter-1.1.2.linux-ppc64le.tar.gz
90b7c7e4b2b94936b5faa3cf2d35509b62ebc0d60b3afe1abaaf03efcd415a4a  pg_exporter-1.1.2.windows-amd64.tar.gz

https://github.com/pgsty/pg_exporter/releases/tag/v1.1.2

v1.1.1

Minor release with new collectors and bug fixes.

New Features:

  • New pg_timeline collector for timeline monitoring
  • New pg_sub_16 collector branch to exclude parallel operations in subscriptions (PostgreSQL 16+ compatibility)

Bug Fixes:

  • Fix: Add coalesce for slotname in pg_recv collector to handle NULL values

Checksums

https://github.com/pgsty/pg_exporter/releases/download/v1.1.1/checksums.txt

fd5ee96511676fc11b975115a4870ed0c811056519f79ad7f24ab7ec538fa278  pg-exporter_1.1.1-1_amd64.deb
b90a08d16a6e4707d82f8f3ae282cb76acb331de607e7544532fd0b774b7aa27  pg-exporter_1.1.1-1_arm64.deb
163955f59a71da48901ffa26bb2f2db0712d31d8aeb1ab3fa463683f719a6d3a  pg-exporter_1.1.1-1_ppc64le.deb
cf4f8bc12bb8a2d1e55553f891fd31c43324e4348249727972eb44f82cd4e6c8  pg_exporter-1.1.1-1.aarch64.rpm
5a425b2f61f308b32f2d107372830c34eb685bfb312ee787f11877a20f1c4a2e  pg_exporter-1.1.1-1.ppc64le.rpm
23606ccea565368971ac2e7f39766455b507021f09457bcf61db13cb10501a16  pg_exporter-1.1.1-1.x86_64.rpm
ce74624eba92573318f50764cee4f355fa1f35697d209f70a4240f8f9d976188  pg_exporter-1.1.1.darwin-amd64.tar.gz
35fba12521dbdcc54a3792278ed4822e4ca9e951665b5e53dff7c2a0f7014ae3  pg_exporter-1.1.1.darwin-arm64.tar.gz
7699bdef15dd306289645beee8d40a123ca75dc988e46d89cdd75a1c1f650bef  pg_exporter-1.1.1.linux-amd64.tar.gz
f4baba59d27a8eb67f0c5209fed7b9f00f78db796e583cc3487701e7803671c6  pg_exporter-1.1.1.linux-arm64.tar.gz
810c3817c27358fa667714f8bfe8d52840a7ea010035e29547919ccb7c9fa781  pg_exporter-1.1.1.linux-ppc64le.tar.gz
3f6df693b3eb92fdaeaeccf99ea7e5977b2c65028a4f00bdfabbc0405b9f5f93  pg_exporter-1.1.1.windows-amd64.tar.gz

https://github.com/pgsty/pg_exporter/releases/tag/v1.1.1

v1.1.0

Build with Go 1.25.5 and latest dependencies, collector updates:

Collector Changes:

  • pg_setting: update PG10-18 compatibility and add missing_ok support.
    • Add 13 new metrics: max_parallel_workers, max_parallel_workers_per_gather, max_parallel_maintenance_workers, shared_buffers, maintenance_work_mem, effective_cache_size, fsync, full_page_writes, autovacuum, autovacuum_max_workers, checkpoint_timeout, checkpoint_completion_target, hot_standby, synchronous_commit, io_method.
    • Rename work_memory_size to work_mem.
    • Change min_version from 9.6 to 10. Use explicit ::int type conversion.
  • pg_size: fix log directory size detection. Check logging_collector instead of matching path patterns.
  • pg_table: replace LATERAL subqueries with JOIN to improve performance. Change tuples and frozenxid from COUNTER to GAUGE. Increase the timeout from 1s to 2s.
  • pg_vacuuming: add a PG17 branch with indexes_total, indexes_processed, and dead_tuple_bytes to track index vacuum progress.
  • pg_query: increase the timeout from 1s to 2s for high-load conditions.
  • pg_io: correct the reuses description from “in reused” to “is reused”.
  • pg_checkpointer: correct the pg_checkpointer_10 description from “9.4+” to “9.4-17”.
  • pg_db_confl: correct the pg_db_confl_15 description from “9.1 - 16” to “9.1 - 15”.
  • Correct format alignment for pg_db, pg_indexing, pg_clustering, and pg_backup.

Other Changes:

Checksums

https://github.com/pgsty/pg_exporter/releases/download/v1.1.0/checksums.txt

9c65f43e76213bb8a49d1eab2c76a27d9ab694e67bc79f0ad12769ea362b5ca2  pg-exporter_1.1.0-1_amd64.deb
bcd2cacb4febc5fb92f9eda8e733c161c8c6721416e16ec91a773503241c972d  pg-exporter_1.1.0-1_arm64.deb
2c9d4a9cb06d07af0b6dd9dd6e568af073dc9f6775abde63b45f0aae34d171b1  pg-exporter_1.1.0-1_ppc64le.deb
2934ab5b0fb16dca5a96ec1e8f230e32c72b30ca076b5e5ddf8ec553c821f7b8  pg_exporter-1.1.0-1.aarch64.rpm
3c9955f31ba93532cc7f95ff60b0658f4b6eca6a827710e2f70c0716b34eab43  pg_exporter-1.1.0-1.ppc64le.rpm
9fdefbd8e7660dcb130207901a27762e0a381857ba8cf12b63184744f92dea05  pg_exporter-1.1.0-1.x86_64.rpm
7159002016754309e0ed625a9a48049d21177883fa11d1e448eb7655ceb690cc  pg_exporter-1.1.0.darwin-amd64.tar.gz
7d55ac5cda0b1fd8ffbd5e76b9c1c1784ac8e353104a206caaadce89adda6d65  pg_exporter-1.1.0.darwin-arm64.tar.gz
8211ec24277554b9b1a36920d7865153e21c2621031d3d08f22d94cdd2ddf02f  pg_exporter-1.1.0.linux-amd64.tar.gz
d17ab7f9bf04442e642483d432d005d25bb62e0c9caa73cb7e69ee19eb89b3ae  pg_exporter-1.1.0.linux-arm64.tar.gz
c074aeb345cc30f7b6e16aa153ae3d9a12789e4425987590c3fd77c4e68a40b6  pg_exporter-1.1.0.linux-ppc64le.tar.gz
13d653e2abb023ce9526bdc2815135b82f49c044d237030f3f56b09fb016fcb7  pg_exporter-1.1.0.windows-amd64.tar.gz

https://github.com/pgsty/pg_exporter/releases/tag/v1.1.0

v1.0.3

  • Build with Go 1.25.4 and latest dependencies
  • Fix #80 Conflict with libpq env variables
  • Change default value of auto-discovery to true by @kadaffy

Checksums

https://github.com/pgsty/pg_exporter/releases/download/v1.0.3/checksums.txt

7efa1a77dfd5b94813c32c7ac015b1d479b1f04fb958f6b1ed5af333e354d015  pg-exporter_1.0.3-1_amd64.deb
41e18bf18eba2ab90ac371bfb46e9152da9fe628ebd8e26766cac08325eb3b07  pg-exporter_1.0.3-1_arm64.deb
7da8ed738d254c120d42aa51d6137f84e7f4e3188bc764d4f9a1438220363a43  pg-exporter_1.0.3-1_ppc64le.deb
a214b555981156da7b7d248b1f728f8ac88a07ac8f77a66c5d8e43b40670d6b4  pg_exporter-1.0.3-1.aarch64.rpm
d876fc66e208612ebffe3c43dabce88b088d915f92584260d710b85a3a131413  pg_exporter-1.0.3-1.ppc64le.rpm
75f62d314fec50c836c534996c884d25ecea77810ab33e7ba0e9c4b783e775b4  pg_exporter-1.0.3-1.x86_64.rpm
47829a19707284bcee1b8dc47cc7d0172398bb533e6b4043950f787486712769  pg_exporter-1.0.3.darwin-amd64.tar.gz
38b6ccb72315cadea542b1f2a7b7022d0e8d48ffd4ab177bb69a0a909b99af6b  pg_exporter-1.0.3.darwin-arm64.tar.gz
36e8dff84d61a7593ff1fcec567ca4ffeaecd0be2f9eabd227ceac71b12a919a  pg_exporter-1.0.3.linux-amd64.tar.gz
6477e8ef873773a09c4f39a29444f21b5b2c71e717e52ca425bcc8e8e5448791  pg_exporter-1.0.3.linux-arm64.tar.gz
a083b51ebed2b280e2eaa0f19558494e7fa6f122a0a86a1d117206fcd090820c  pg_exporter-1.0.3.linux-ppc64le.tar.gz
a1f9b27b7190f478726d96f270a72d9dc4d3f2bcc3b0326b7c4a2607e62ea588  pg_exporter-1.0.3.windows-amd64.tar.gz

https://github.com/pgsty/pg_exporter/releases/tag/v1.0.3

v1.0.2

  • Build with Go 1.25.0 and the latest dependencies.
  • Add a dedicated website and homepage: https://exp.pgsty.com
  • Use GoReleaser and CI/CD to release for more operating systems and architectures:
    • Add Windows amd64 support.
    • Add Linux ppc64le support.

Checksums

https://github.com/pgsty/pg_exporter/releases/download/v1.0.2/checksums.txt

683bf97f22173f2f2ec319a88e136939c2958a1f5ced4f4aa09a1357fc1c44c5  pg-exporter_1.0.2-1_amd64.deb
f62d479a92be2d03211c162b8419f968cea87ceef5b1f25f2bcd390e0b72ccb5  pg-exporter_1.0.2-1_arm64.deb
e1bbfc5a4c1b93e6f92bc7adcb4364583ab763e76e156aa5c979d6d1040f4c7a  pg-exporter_1.0.2-1_ppc64le.deb
f51d5b45448e6bbec3467d1d1dc049b1e16976f723af713c4262541ac55a039c  pg_exporter-1.0.2-1.aarch64.rpm
18380011543674e4c48b2410266b41165974d780cbc8918fc562152ba623939e  pg_exporter-1.0.2-1.ppc64le.rpm
198372d894b9598c166a0e91ca36d3c9271cb65298415f63dbffcf6da611f2bb  pg_exporter-1.0.2-1.x86_64.rpm
cbe7e07df6d180507c830cdab4cf86d40ccd62774723946307b5331d4270477d  pg_exporter-1.0.2.darwin-amd64.tar.gz
20c4a35fa244287766c1d1a19cd2e393b3fa451a96a81e5635401e69bef04b97  pg_exporter-1.0.2.darwin-arm64.tar.gz
d742111185f6a89fff34bfd304b851c8eb7a8e38444f0220786e11ed1934eff1  pg_exporter-1.0.2.linux-amd64.tar.gz
0b1f4c97c1089c4767d92eb22419b8f29c9f46fb90ddfd1e8514cc42dc41054f  pg_exporter-1.0.2.linux-arm64.tar.gz
895083fd2c7fc5409cc1a2dbaaef1e47ac7aa6a3fd5db2359012922d90bcdcc3  pg_exporter-1.0.2.linux-ppc64le.tar.gz
5f751228e7120604af9a482fb70197489fa633c38a0f2b6a3489393fbc6a10aa  pg_exporter-1.0.2.windows-amd64.tar.gz

https://github.com/pgsty/pg_exporter/releases/tag/v1.0.2

v1.0.1

  • Add dockerhub images: pgsty/pg_exporter
  • Update Go dependencies to the latest version. Build with Go 1.24.5
  • Disable pg_tsdb_hypertable by default because the timescaledb catalog has changed.

Checksums

d5e2d6a656eef0ae1b29cd49695f9773  pg_exporter-1.0.1-1.aarch64.rpm
cb01bb78d7b216a235363e9342803cb3  pg_exporter-1.0.1-1.x86_64.rpm
67093a756b04845f69ad333b6d458e81  pg_exporter-v1.0.1.darwin-amd64.tar.gz
2d3fdc10045d1cf494b9c1ee7f94f127  pg_exporter-v1.0.1.darwin-arm64.tar.gz
e242314461becfa99c3978ae72838ab0  pg_exporter-v1.0.1.linux-amd64.tar.gz
63de91da9ef711a53718bc60b89c82a6  pg_exporter-v1.0.1.linux-arm64.tar.gz
718f6afc004089f12c1ca6553f9b9ba5  pg-exporter_1.0.1_amd64.deb
57da7a8005cdf91ba8c1fb348e0d7367  pg-exporter_1.0.1_arm64.deb

https://github.com/pgsty/pg_exporter/releases/tag/v1.0.1

v1.0.0

Add PostgreSQL 18 metrics support

  • new collector branch pg_wal_18:
  • remove write, sync, write_time, sync_time metrics
  • move to pg_stat_io
  • new collector branch pg_checkpointer_18:
  • new metric num_done
  • new metric slru_written
  • new collector branch pg_db_18:
  • new metric parallel_workers_to_launch
  • new metric parallel_workers_launched
  • new collector branch pg_table_18:
  • table_parallel_workers_to_launch
  • table_parallel_workers_launched
  • new collector branch pg_io_18:
  • new series about WAL statistics
  • new metric read_bytes
  • new metric write_bytes
  • new metric extend_bytes
  • remove op_bytes due to fixed value
  • new collector branch pg_vacuuming_18
  • new metric delay_time
8637bc1a05b93eedfbfd3816cca468dd  pg_exporter-1.0.0-1.aarch64.rpm
a28c4c0dcdd3bf412268a2dbff79f5b9  pg_exporter-1.0.0-1.x86_64.rpm
229129209b8e6bc356c28043c7c22359  pg_exporter-v1.0.0.darwin-amd64.tar.gz
d941c2c28301269e62a8853c93facf12  pg_exporter-v1.0.0.darwin-arm64.tar.gz
5bbb94db46cacca4075d4c341c54db37  pg_exporter-v1.0.0.linux-amd64.tar.gz
da9ad428a50546a507a542d808f1c0fa  pg_exporter-v1.0.0.linux-arm64.tar.gz
0fa2395d9d7a43ab87e5c87e5b06ffcc  pg-exporter_1.0.0_amd64.deb
fed56f8a37e30cc59e85f03c81fce3f5  pg-exporter_1.0.0_arm64.deb

https://github.com/pgsty/pg_exporter/releases/tag/v1.0.0

v0.9.0

Default Collectors

  • new metrics collector for timescaledb hypertable
  • new metrics collector for citus dist node
  • new metrics collector for pg_wait_sampling wait event profile
  • pg_slot overhaul: Add 16/17 pg_replication_slot metrics
  • allow pg_slot collector run on replica since 16/17
  • refactor pg_wait collector to agg from all processes
  • restrict pg_clustering, pg_indexing, pg_vacuuming run on primary
  • mark all reset_time as GAUGE rather than COUNTER
  • fix pg_recovery_prefetch_skip_fpw type from GAUGE to COUNTER
  • fix pg_recv.state type from LABEL to GAUGE
  • Format collector in compact mode
  • new default metric pg_exporter_build_info / pgbouncer_exporter_build_info
  • add server_encoding to pg_meta collector
  • add 12 new setting metrics to pg_setting collector
  • wal_block_size
  • segment_size
  • wal_segment_size
  • wal_level
  • wal_log_hints
  • work_mem
  • hugepage_count
  • hugepage_status
  • max_wal_size
  • min_wal_size
  • max_slot_wal_keep_size

Exporter Codebase

  • normalize collector branch name with min pg ver suffix
  • Add license file to binary packages
  • move pgsty/pg_exporter repo to pgsty/pg_exporter
  • refactor server.go to reduce Compatible and PostgresPrecheck complexity
  • rename metrics collector with extra number prefix for better sorting
  • bump dependencies to the latest version
  • execute fatal collectors ahead of all non-fatal collectors, and fail fast

https://github.com/pgsty/pg_exporter/releases/tag/v0.9.0

v0.8.1

https://github.com/pgsty/pg_exporter/releases/tag/v0.8.1

v0.8.0

https://github.com/pgsty/pg_exporter/releases/tag/v0.8.0

v0.7.1

Routine update with dependabot

https://github.com/pgsty/pg_exporter/releases/tag/v0.7.1

v0.7.0

Refactor the codebase for the latest Go version.

https://github.com/pgsty/pg_exporter/releases/tag/v0.7.0

v0.6.0

https://github.com/pgsty/pg_exporter/releases/tag/v0.6.0

v0.5.0

Exporter Enhancement

  • Build rpm & deb with nfpm
  • Add column.default, replace when metric value is NULL
  • Add column.scale to multiply float/int values by a scale factor, such as conversion from µs to seconds
  • Fix /stat endpoint output
  • Add docker container pgsty/pg_exporter

Metrics Collector

  • scale bgwriter & pg_wal time unit to second
  • remove pg_class collector and move it to pg_table & pg_inex
  • add pg_class metrics to pg_table
  • add pg_class metrics to pg_index
  • enable pg_table_size by default
  • scale pg_query pg_db pg_bgwriter pg_ssl pgbouncer_stat time metrics to second

https://github.com/pgsty/pg_exporter/releases/tag/v0.5.0

v0.4.1

  • Update default collectors:
    • Exclude citus & timescaledb schemas from object monitoring.
    • Prevent duplicate pg_statio tuples.
    • Support pgBouncer v1.16.
    • Fix overlapping pg_repl collectors on pg 12.
  • Add the -T connect-timeout PG_EXPORTER_CONNECT_TIMEOUT parameter for remote PostgreSQL monitoring.
  • Rename pg_exporter.yaml to pg_exporter.yml in the RPM package.

https://github.com/pgsty/pg_exporter/releases/tag/v0.4.1

v0.4.0

  • Add PG 14 support
  • Update the default metrics configuration. The old configuration remains supported
  • add auto-discovery , include-database and exclude-database option
  • Add multiple database monitoring implementations (with auto-discovery = on)

https://github.com/pgsty/pg_exporter/releases/tag/v0.4.0

v0.3.2

  • fix shadow DSN corner case
  • fix typo & docs

https://github.com/pgsty/pg_exporter/releases/tag/v0.3.2

v0.3.1

Fix default configuration errors, particularly for versions before 13.

  • Account for the primary_conninfo setting being available only from PG13.
  • Add the funcid label to pg_func to prevent duplicate labels from function names.
  • Fix the version string to pg_exporter.

https://github.com/pgsty/pg_exporter/releases/tag/v0.3.1

v0.3.0

https://github.com/pgsty/pg_exporter/releases/tag/v0.3.0

  • Update the default configuration to support PostgreSQL 13 metrics, including pg_slru, pg_shmem, pg_query13, and pg_backup.
  • Add REST APIs for health and recovery status checks.
  • Add a dummy server that returns pg_up 0 before PgExporter initialization.
  • Add sslmode=disable to the URL if sslmode is absent.
  • Fix typos and bugs.

v0.2.0

  • add yum package and linux service definition
  • add a ‘skip’ flag into query config
  • fix pgbouncer_up metrics
  • add conf reload support

https://github.com/pgsty/pg_exporter/releases/tag/v0.2.0

v0.1.2

  • fix pgbouncer_up metrics
  • add dynamic configuration reload
  • remove ‘shard’ related logic
  • add a ‘bulky’ mode to default settings

https://github.com/pgsty/pg_exporter/releases/tag/v0.1.2

v0.1.1

Fix a startup hang that occurs if any query fails.

https://github.com/pgsty/pg_exporter/releases/tag/v0.1.1

v0.1.0

This is the first stable release.

https://github.com/pgsty/pg_exporter/releases/tag/v0.1.0

v0.0.4

This release passed production tests on 200+ nodes for about 2 weeks.

https://github.com/pgsty/pg_exporter/releases/tag/v0.0.4

v0.0.3

v0.0.3 passed production tests.

This version is already tested in a production environment.

The project changes rapidly. Use this version with caution in production.

https://github.com/pgsty/pg_exporter/releases/tag/v0.0.3

v0.0.2

This version is ready for testing.

https://github.com/pgsty/pg_exporter/releases/tag/v0.0.2

v0.0.1

Add pgBouncer mode

https://github.com/pgsty/pg_exporter/releases/tag/v0.0.1