Skip to content

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

Return to the regular view of this page.

PG Exporter 1.6.1 Documentation

Advanced PostgreSQL & pgBouncer Metrics Exporter for Prometheus

Monitor PostgreSQL with 460 metric definitions, declarative configuration, and dynamic planning.

Get Started | GitHub | Live Demo

Features

FeatureDescription
Comprehensive Metrics460 metric definitions cover nearly every statistics view in PostgreSQL (10-19+) and pgBouncer (1.8-1.26+)
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.6.1
  • Default config support: PostgreSQL 10-19+
  • Legacy configuration support: PostgreSQL 9.1–9.6, using the separately maintained legacy/ configuration; see Installation
  • pgBouncer support: 1.8-1.26+

The v1.6.1 default bundle contains 58 YAML files (57 collector files and one configuration reference), 96 version/role branches, and 59 metric namespaces. The 460 metric names are deduplicated across branches, including disabled collectors and two unexpanded HISTOGRAM definitions. Actual time-series counts depend on versions, objects, labels, and histogram buckets.

See Release Notes for the full history.

Before upgrading, review v1.6.1 upgrade notes, v1.6.0 metric changes, and the dashboard/alert migration checklist. Unchanged metric names do not guarantee unchanged labels, state encodings, or semantics. PostgreSQL major upgrades also select different collector branches.

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:1.6.1
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.6.1 (built with go1.27.4 on linux/amd64)

Step 2: Create a Monitoring User

Create a dedicated monitoring user on the target PostgreSQL instance. Start with the built-in pg_monitor role in PostgreSQL 10+:

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

On PostgreSQL 10–13, an administrator must also run the following grant in the exporter’s main connection database to read subscription OIDs. Granting it only in the database owning the subscription is insufficient. This does not expose the password-bearing subconninfo column. PostgreSQL 14+ needs no extra grant under standard catalog ACLs.

GRANT SELECT (oid) ON pg_catalog.pg_subscription 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 main target is reachable and has no fatal collector error
pg_version 170000    # version in server_version_num format
pg_in_recovery 0     # 1 on replicas, 0 on primaries

pg_up 1 indicates that the main target was reachable and had no fatal collector error during the last valid scrape. The pg_exporter.yml bundle defines 460 distinct metric names (pg_db_*, pg_table_*, pg_wal_*, and others), and outputs the metrics that apply to the server version, role, and database objects. If pg_up is 0, run pg_exporter --log.level=debug to inspect connection and fatal query errors; an interrupted initial precheck can also leave pg_up at 0 temporarily. For the difference between HTTP health checks and scrape metrics, see the API Reference.

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, role, tags; predicates run during refresh, so also check query stats and logs)
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.

Repository installation uses the current package in the repository, which can lag the GitHub release. Use the versioned release artifacts below when you need v1.6.1.

Pigsty

Use Pigsty for the simplest installation. Pigsty is a complete PostgreSQL distribution with monitoring based on pg_exporter, VictoriaMetrics (Prometheus-compatible metric scraping and querying), and Grafana. It configures the metrics, alert rules, 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.6.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:1.6.1

# 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:1.6.1

# 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:1.6.1
Note

The image is built from scratch and includes the system CA bundle and license, but no shell. Publicly trusted certificates can use the bundled roots; when you use a private CA with sslmode=verify-ca or verify-full, mount the private CA and set sslrootcert.

Compatibility

The default configuration supports PostgreSQL 10-19+. For end-of-life PostgreSQL versions, use the legacy configuration bundle maintained separately on main. It is not included in binary tarballs or RPM/DEB packages; download it separately.

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:

curl -fSL https://raw.githubusercontent.com/pgsty/pg_exporter/v1.6.1/legacy/pg_exporter.yml -o pg_exporter-legacy.yml
PG_EXPORTER_CONFIG=pg_exporter-legacy.yml pg_exporter

For PostgreSQL 9.1, use configuration from the v1.6.1 tag or main at 282e19d or later. This fixes OID 0 errors on tables without TOAST relations that caused all table-size metrics to disappear. Legacy configuration is still not bundled in binary archives or RPM/DEB packages and must be downloaded separately.

The built-in pgBouncer collectors support pgBouncer 1.8+; the SHOW STATS fields they read are available starting in 1.8.

pgBouncer VersionSupport Status
1.8.x ~ 1.26+✅ 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 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:

  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.
  • 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:

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.
  • Explicit scale and default values must be finite; since v1.6.1, NaN and infinity are rejected
  • Scalar queries (GAUGE / COUNTER) must return one row per label set. Since v1.6.1, duplicate scalar label sets fail that collector for the current scrape and discard its results, isolating the error from the whole scrape. Histogram-only collectors still combine multiple observations with the same labels.
  • 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
  • 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:

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

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.

Request Lifetime

Since v1.6.0, at most two metrics requests are admitted across collection, waiting, and response writing. Scrapes still run serially; one request can wait within its remaining budget, and further concurrent requests receive HTTP 503. The budget defaults to 30 seconds and is shortened by a valid, finite, positive X-Prometheus-Scrape-Timeout-Seconds header. A request canceled while waiting does not start SQL work.

After request cancellation, the exporter does not start the next collector or database. A collector already started with a positive timeout keeps its shared predicate-and-query deadline and caches a successful refresh. A negative timeout disables that deadline, so the query cancels with the request. An interrupted scrape returns 503 if the connection still accepts a response. Driver and network blocking mean these deadlines are not hard wall-clock caps; configure connect_timeout in the DSN to bound connection handshakes.

Interrupted rounds do not increment pg_exporter_scrape_error_count or pg_exporter_server_scrape_error_count, and log INFO interrupted; query error counters and fatal-query ERROR logs remain active. A real failure that overlaps request cancellation can therefore be omitted from those two round counters. Without request cancellation, connection/precheck failures and fatal query failures (including their own timeouts) still count as errors; non-fatal failures remain visible in query-level counters.

Failed refreshes keep the existing failure TTL. In particular, a fatal collector with a negative timeout caches a fatal failure when canceled; later active scrapes can count that cached failure and report pg_up 0 until a refresh succeeds. Keep positive timeouts on fatal collectors. See Scrape Lifetime for rationale.

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
  • 130002 = 13.2
  • 160001 = 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 on the first scrape, configuration reload, or metadata change. 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.

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

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,
      relname AS 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–17)"
  min_version: 140000
  max_version: 180000
  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)'

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.6.0 → v1.6.1: built-in SQL metric names, label keys, types, buckets, and routes are unchanged. pg_table emits age = 0 for relfrozenxid = 0 (such as partitioned parents), and zero-fills missing index/table estimates to avoid losing valid statistics or producing NaN. pg_table_size excludes pg_temp* and pg_toast*. Duplicate label rows in custom scalar queries fail only that collector, and scale / default must be finite.
  • Exporter v1.5.0 → v1.6.0: bundled SQL metric names, label keys, types, and units stay unchanged. Cross-database progress metrics now emit the numeric OID as relname for user relations in other databases while still resolving names for the current database and shared catalogs; dashboards retain datname and pid. Interrupted rounds no longer increment target error counters, and HTTP health is determined separately from scrape success.
  • Exporter v1.4.1 → v1.5.0: bundled SQL metric names, types, and units stay unchanged, but pg_sub_* adds datname and pg_recv_state corrects 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_count broadens to table plus sequence synchronization errors, and pg_subrel_count includes sequences. pg_sub_has_worker distinguishes a subscription row from a running apply worker; the presence of pg_sub_id alone is insufficient.
  • Crossing PG17 / PG18: some pg_bgwriter_* metrics need to move to pg_checkpointer_* or backend-filtered I/O metrics. From PG18 onward, pg_wal_write, pg_wal_sync, pg_wal_write_time, and pg_wal_sync_time need to move to pg_io_*{object="wal"}, with corresponding label aggregation changes. See the metric-by-metric migration table.

See v1.6.1 release notes, v1.6.0 release notes, and the PG19 metrics matrix. PG19 support first shipped in v1.3.0; acceptance evidence covers 19 RC1. These notes do not imply runtime acceptance 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:

(pg_up{job="pg19"} == 1)
unless on (job, instance)
pg_wal_bytes{job="pg19"}

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

# 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. In v1.5.0, each response reads one atomic state snapshot, so its HTTP status and body always describe the same state. The cached state can still lag behind the database. A successful PgBouncer probe maps to primary; it does not describe the role of its PostgreSQL backend.

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.6.1",branch="main",revision="<git-sha>",builddate="<build-date>",goversion="go1.27.4",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>

Since v1.6.0, at most two metrics requests are admitted across collection, waiting, and response writing. Scrapes still run serially; one request can wait within its remaining budget, and further concurrent requests receive HTTP 503. The budget defaults to 30 seconds and is shortened by a valid, finite, positive X-Prometheus-Scrape-Timeout-Seconds header. A request canceled while waiting does not start SQL work.

After request cancellation, the exporter does not start the next collector or database. A collector already started with a positive timeout keeps its shared predicate-and-query deadline and caches a successful refresh. A negative timeout disables that deadline, so the query cancels with the request. An interrupted scrape returns 503 if the connection still accepts a response. Driver and network blocking mean these deadlines are not hard wall-clock caps; configure connect_timeout in the DSN to bound connection handshakes.

Interrupted rounds do not increment pg_exporter_scrape_error_count or pg_exporter_server_scrape_error_count, and log INFO interrupted; query error counters and fatal-query ERROR logs remain active. A real failure that overlaps request cancellation can therefore be omitted from those two round counters. Without request cancellation, connection/precheck failures and fatal query failures (including their own timeouts) still count as errors; non-fatal failures remain visible in query-level counters.

Failed refreshes keep the existing failure TTL. In particular, a fatal collector with a negative timeout caches a fatal failure when canceled; later active scrapes can count that cached failure and report pg_up 0 until a refresh succeeds. Keep positive timeouts on fatal collectors. See Scrape Lifetime for rationale.

Self-Monitoring Metrics

Built-in PostgreSQL metrics default to the pg prefix; PgBouncer uses pgbouncer. --namespace changes these prefixes, and invalid namespaces are rejected at startup. It does not rename metrics defined in YAML.

MetricTypeLabelsMeaning
pg_upGauge—Primary-target availability seen by scrapes; see interruption rules below
pg_versionGauge—Primary target version number
pg_in_recoveryGauge—1 on standby, 0 on primary; use when pg_up = 1
pg_exporter_build_infoGaugeversion, revision, branch, builddate, goversion, goos, goarchConstant 1 with build metadata labels
pg_exporter_upGauge—Constant 1
pg_exporter_uptimeGauge—Seconds since exporter initialization
pg_exporter_scrape_total_countCounter—Scrape rounds
pg_exporter_scrape_error_countCounter—Rounds where the primary target had a connection or fatal collector error
pg_exporter_scrape_durationGauge—Duration of the last complete scrape round, in seconds
pg_exporter_last_scrape_timeGauge—Unix timestamp when the last scrape round finished
pg_exporter_server_scrape_durationGaugedatnameDuration of the database’s last scrape round, in seconds
pg_exporter_server_scrape_total_secondsGaugedatnameCumulative scrape duration for the database, in seconds
pg_exporter_server_scrape_total_countGaugedatnameScrape rounds for the database
pg_exporter_server_scrape_error_countGaugedatnameConnection or fatal collector errors for the database
pg_exporter_query_scrape_total_countGaugedatname, queryCollector invocations, including cache hits and predicate skips
pg_exporter_query_scrape_error_countGaugedatname, queryCollector invocation errors
pg_exporter_query_scrape_hit_countGaugedatname, queryResult cache hits
pg_exporter_query_scrape_metric_countGaugedatname, querySamples in the collector’s current result
pg_exporter_query_scrape_durationGaugedatname, queryDuration of the last actual execution, in seconds; unchanged on cache hit
pg_exporter_query_scrape_predicate_skip_countGaugedatname, querySkips because a predicate returned false, NULL, or zero rows
pg_exporter_query_cache_ttlGaugedatname, queryRemaining result cache lifetime, in seconds

These series also receive configured constant labels. On pg_exporter_build_info, build values for version, revision, branch, builddate, goversion, goos, and goarch take precedence over user labels. Invalid labels on built-in database/query samples cause a warning and that sample is skipped to avoid a panic. Cumulative database/collector counters are exposed as Gauges. Replanning a server resets collector statistics; configuration reload also triggers replanning. Recreating a database connection object resets that database’s statistics.

--disable-intro suppresses all built-in metrics in this table, including pg_up. YAML metrics, Go/process metrics, and HTTP health endpoints remain available.

On interruption, pg_up preserves the primary target’s previous availability state, or stays 1 if the current precheck already succeeded. If the first precheck is interrupted before succeeding, it remains 0 and recovers on a later successful scrape. Interrupted child databases follow the same per-database rule without incrementing primary-target error counters.

Health Checks

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

GET /up

After initialization, HTTP health state is updated only by the once-per-second background probe. Slow scrapes do not hold the probe lock or overwrite newer probe results. HTTP health requests read the snapshot without running SQL. pg_up and pg_in_recovery remain scrape metrics: a fatal collector failure can set pg_up to 0 while /up still returns 200 if the database is reachable. Connection pool limits are three for the PostgreSQL main target, two for PgBouncer, and one per discovered database.

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, query plans, caches, and query statistics. A parsing failure preserves the previous plan and caches. Empty YAML is a valid empty configuration; a successful reload clears the collectors. Directory mode permits partial file loading; see Configuration Loading. 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 the collectors selected in the primary target’s current plan. Predicates run during refresh and are not evaluated by this endpoint.

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: --web.telemetry-path rejects empty paths, conflicts with built-in endpoints, and non-canonical paths such as //metrics. v1.5.0 also verifies that the active HTTP mux selects the metrics handler, preventing escaped paths from returning the landing page or a redirect. Prefer an unescaped path such as /metrics.

Connection URL Sources

The exporter checks these sources in order, skipping empty command-line and environment values:

  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)

Once PG_EXPORTER_URL_FILE is selected, an unreadable, empty, or whitespace-only file prevents startup; it does not fall back to the local default.

v1.5.0 validates URLs, percent escapes, and query parameter names strictly. Names cannot be empty or contain whitespace or =, and URLs cannot contain unescaped #. Invalid input stops startup with fixed diagnostics that omit the original connection string, preventing password disclosure or silent loss of TLS settings. Logs redact userinfo passwords and password= / sslpassword= values in valid URLs. Hostless URLs such as postgresql://?host=/var/run/postgresql retain // during normalization.

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+)

On PostgreSQL 10–13, an administrator must also run the following grant in the exporter’s main connection database to read subscription OIDs. Granting it only in the database owning the subscription is insufficient. This does not expose the password-bearing subconninfo column. PostgreSQL 14+ needs no extra grant under standard catalog ACLs.

GRANT SELECT (oid) ON pg_catalog.pg_subscription TO monitor;

Size CONNECTION LIMIT for the number of discovered databases. A limit that is too low can prevent connections to additional databases. Keep a 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
ExecReload=/bin/kill -HUP $MAINPID
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 daemon-reload               # refresh systemd after upgrading the unit
sudo systemctl enable --now pg_exporter    # start and enable at boot
sudo systemctl status pg_exporter          # check status
sudo systemctl reload pg_exporter          # reload collector configuration through SIGHUP without restarting
journalctl -u pg_exporter -f               # follow logs
curl -X POST localhost:9630/reload         # reload collector configuration over HTTP

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:1.6.1

Docker Compose:

services:
  pg_exporter:
    image: pgsty/pg_exporter:1.6.1
    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 image is built from scratch and includes the system CA bundle and license, but no shell. Publicly trusted certificates can use the bundled roots; when you use a private CA with sslmode=verify-ca or verify-full, mount the private CA and set sslrootcert.

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:1.6.1
        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" \
  --include-database=""
# The exclusion list above is the default; set --include-database for 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 or dropped databases are added or removed during subsequent prechecks
  • v1.5.0 uses lib/pq to resolve the actual database identity. When replacing a database name, it removes conflicting dbname / database query parameters, and v1.6.1 also removes conflicting service=. It preserves special characters to prevent discovered connections from converging on the same database. Removing or replacing child targets waits for active collection before closing old pools.
  • Database scrapes remain sequential. Allow enough scrape timeout for prechecks and queries across all databases; in v1.6.0, a canceled request does not start subsequent databases or collectors
  • The PostgreSQL main connection pool uses up to three connections, and each discovered database uses one connection. The PgBouncer connection pool uses up to two connections to separate serial scrapes from the independent health probe

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 pg_exporter release is v1.6.1.

VersionDateSummaryGitHub
v1.6.12026-11-11Table statistics fixes, duplicate scalar isolation, connection fixes, systemd reload, Go 1.27.4v1.6.1
v1.6.02026-11-09Decoupled health probe, bounded scrapes, progress label and container CA fixesv1.6.0
v1.5.02026-10-23Connection safety, discovery, health and replication fixes; Go 1.27.3v1.5.0
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.6.1

Released on 2026-11-11.

PG Exporter v1.6.1 is a maintenance release that corrects table statistics, isolates collector errors that could break a whole scrape, and fixes connection edge cases. The build toolchain moves to Go 1.27.4, while the PostgreSQL driver remains lib/pq 1.12.3. Built-in SQL metric names, label keys, types, buckets, CLI flags, and HTTP routes are unchanged.

Fixes and Improvements

  • Isolate duplicate scalar rows: if a GAUGE or COUNTER query returns multiple rows with the same labels, mark that collector as failed and discard its output before Prometheus gathers it. Other collectors continue after nonfatal failures; fatal: true retains its semantics. Histogram-only collectors still merge same-label observations into one snapshot distribution. Cross-collector metric conflicts still require configuration fixes.
  • Correct partitioned and unindexed table statistics: all four pg_table version branches emit age = 0 for relfrozenxid = 0, including partitioned parents, instead of 2147483647. tbl_scan, tup_read, and n_tup_mod individually coalesce nulls before addition, so missing index counts no longer suppress valid sequential-scan statistics. Null live/dead/modified row estimates become zero rather than NaN.
  • Avoid temporary-table size failures: pg_table_size excludes pg_temp* and pg_toast*, avoiding reads of other sessions’ temporary tables and separate TOAST accounting. The source tag also fixes OID 0 errors in PostgreSQL 9.1 legacy configuration for tables without TOAST, preventing loss of the entire table-size metric set. Download legacy configuration separately.
  • Correct activity durations and TimescaleDB identifiers: pg_activity clamps negative durations to zero when state, transaction, or session timestamps exceed the query time reference. Disabled-by-default pg_tsdb_hypertable correctly quotes schema/table names containing uppercase or special characters. HELP text is aligned for transaction/session start, index build stages, checkpoint counts, and table main-fork sizes.
  • Fix connection URLs and log redaction: hostless URLs such as postgresql://?host=/var/run/postgresql retain // during normalization so lib/pq recognizes them. Auto-discovery removes conflicting service= when selecting a child database. Logs also redact sslpassword=.
  • Improve connection-pool cleanup: after removing or replacing child targets, auto-discovery waits for active collection before closing old pools. Closing clears pool references and safely handles uninitialized or already-closed pools. Reload still reuses existing pools and clears collection plans rather than recreating all child connections.
  • Strengthen validation and built-in metric handling: configuration rejects nonfinite scale / default, and startup rejects invalid --namespace. Invalid built-in labels, such as non-UTF-8 database names, produce warnings and skip samples instead of panicking. Constant user labels cannot override reserved build fields such as version and revision.
  • Fix diagnostics and direct-call edge cases: HTML explain pages display predicate cache TTL correctly. Direct collector calls execute queries for cold caches or zero TTL even without a server scrape timestamp. Explicit Server.Plan(...) preserves same-name versioned queries by branch key.
  • Update builds and service management: packaged systemd units add ExecReload for systemctl reload pg_exporter. Standalone Docker builds accept version, branch, revision, and build-date arguments; make docker-build supplies them. Ordinary builds without arguments retain HEAD / unknown revision/date values. The toolchain moves to Go 1.27.4 with routine dependency updates.

Upgrade Notes

  1. Upgrade the binary and merge collector YAML. Packages preserve locally modified /etc/pg_exporter.yml and /etc/default/pg_exporter. Deploy the new SQL to obtain table statistics, activity duration, and TimescaleDB fixes. Default configuration still has 58 YAML files, 96 branches, 59 namespaces, and 460 deduplicated metric definitions.
  2. Review custom collectors. Scalar queries need one row per label set; scale and default must be finite. Histogram-only queries can still return multiple observations per label set. Partitioned-parent freeze age is now zero, and unindexed table totals or previously NaN row estimates may change.
  3. Update service units and restart after upgrading the binary. Run sudo systemctl daemon-reload after installing the new unit, then sudo systemctl restart pg_exporter for a new binary or process arguments. Later YAML-only changes can use sudo systemctl reload pg_exporter or POST /reload.
  4. Download legacy YAML separately for PostgreSQL 9.1–9.6. Use configuration from v1.6.1 or main at 282e19d or later. Binary archives and RPM/DEB packages still bundle only PostgreSQL 10+ defaults.

When upgrading from v1.5.0 or earlier, also review v1.6.0 health probes, scrape budgets, and cross-database progress labels, plus v1.5.0 subscription labels, receiver states, and PostgreSQL 10–13 privileges. See the full metric compatibility matrix.

Verification Scope

The v1.6.1 tag points to d0dead1. CI and Release workflows passed module/generated-config checks, the full race suite, Go 1.21 HTTP mux compatibility, go vet, six-target cross-compilation, container checks, and package/checksum checks. Regressions cover duplicate scalar isolation, direct cold-cache/zero-TTL collection, namespaces/build labels, hostless URLs, service= removal, sslpassword redaction, predicate HTML rendering, finite configuration values, and SQL invariants.

Release acceptance covers 12 public artifacts and checksums, amd64/arm64 Docker images, ARM64 DEB installation on Debian 12, ARM64 RPM installation on Rocky Linux 9, and real non-superuser scrapes against PostgreSQL 10–18 and 19 RC1 primaries, PostgreSQL 18 and 19 RC1 streaming replicas, PgBouncer 1.26.1, and PostgreSQL 9.1–9.6 with separate legacy configuration. Scenarios include discovery/database removal, HTTP/SIGHUP reload, pg_stat_statements, unindexed/partitioned/temporary tables, and active transactions. Legacy acceptance does not imply backporting modern pg_temp* filtering or COALESCE fixes. Windows, Linux ppc64le, and Intel macOS were covered only by builds/checksums; package container checks do not prove real systemd startup. PostgreSQL 19 evidence is limited to RC1, not all later builds or production workloads. Experimental snort is not included in v1.6.1.

SHA-256 Checksums

SHA256 checksums

Download asset
FileChecksum
pg-exporter-1.6.1-1.aarch64.rpm Linuxarm64SHA-256d0612ad9294497830892a59d302e7f92510ffd7baca4347b7f0b2438efc90277
pg-exporter-1.6.1-1.ppc64le.rpm LinuxSHA-25673fe4587efebeb444bf1b80730352bc07e22fcd88b0ac17acb6fb745ec26b9b5
pg-exporter-1.6.1-1.x86_64.rpm Linuxamd64SHA-256c20c8a802466776f60b7e95103013bb4d461ac7dab76e3d139c3c9158d3f2c82
pg-exporter_1.6.1-1_amd64.deb Linuxamd64SHA-2560d6fe86ac43c707accfe10bf90af7b3c61e64242b7d916afff15fe3694a8e5fc
pg-exporter_1.6.1-1_arm64.deb Linuxarm64SHA-256a055f9a724c4c5eb3ac436756448c4ad76024d1d7db5087d72f4369daaeb2ab4
pg-exporter_1.6.1-1_ppc64le.deb LinuxSHA-256f8500d010e05bd220c1e0978f27f6b053663ec7d0bdeab2bb85088d87c388d4c
pg_exporter-1.6.1.darwin-amd64.tar.gz macOSamd64SHA-256496c42f329fc265e952c964afaef29ebc7d2d4640180872a735a84eebb962774
pg_exporter-1.6.1.darwin-arm64.tar.gz macOSarm64SHA-2569ace0b48115497f2b3d7d9e1660e13e6a778472c66c8ec5ff679faa2fa61c662
pg_exporter-1.6.1.linux-amd64.tar.gz Linuxamd64SHA-256e8fdf64c352081720a53420a2c7ea095654078d5fab5f6213786bb6476791fdf
pg_exporter-1.6.1.linux-arm64.tar.gz Linuxarm64SHA-25691da5400ae31d42925af721c7d5f8eb0befcbb104d8a14ae5f08707abb5e333b
pg_exporter-1.6.1.linux-ppc64le.tar.gz LinuxSHA-256769e9e56f91787f21478301f9fab1cb7c2791c74f8c355d8e9fbdf818964a5fb
pg_exporter-1.6.1.windows-amd64.tar.gz Windowsamd64SHA-2560e118a9815138a6dc0fed95d934aea0ad84dd4a58139371c2d16e47f85681066

GitHub release · SHA256 checksums · Full changes · Collector documentation

v1.6.0

Release date: 2026-11-09.

PG Exporter v1.6.0 decouples health probing from metrics scrapes, bounds overlapping scrapes and waits, preserves completed bounded refreshes when a client disconnects, and fixes cross-database progress labels. It also adds container trust roots and refreshes dependencies. The release builds with Go 1.27.3 and lib/pq 1.12.3.

Fixes and Improvements

  • Independent health probe: slow metrics scrapes no longer block the background probe, and finishing scrapes no longer overwrite newer reachability or role observations. After initialization, HTTP health state is written only by the probe; pg_up and pg_in_recovery still reflect scrape outcomes. /up can return HTTP 200 while a fatal collector sets pg_up to 0 if the database remains reachable.
  • Bounded scrape admission: at most two metrics requests are admitted across collection, waiting, and response writing. Scrapes still run serially; one request can wait and reuse warm cache, and further requests receive HTTP 503. Waiting is cancelable and starts no SQL work. Request budgets default to 30 seconds and honor a valid, finite, positive Prometheus scrape-timeout header when shorter.
  • Collector-boundary cancellation: after request cancellation, no further collector or database starts. An already started collector with a positive timeout keeps its shared predicate-and-query deadline and caches a successful refresh instead of poisoning shared cache for later scrapers. A negative timeout disables the collector deadline, so SQL cancels with the request.
  • Separate interruption from target errors: interrupted rounds log INFO interrupted and do not increment exporter or server scrape error counters. Availability retains its prior value, or becomes true after the current precheck succeeds. Uncanceled connection failures and fatal collector failures still count as errors. Query-level error counters and fatal-query ERROR logs keep their existing behavior.
  • Accurate progress labels: pg_vacuuming, pg_indexing, and pg_clustering remain cluster-wide and keep three queries per refresh. Relations in the connected database and shared catalogs resolve to names; user relations in other databases emit the numeric OID as relname while keeping datname and pid, preventing accidental local OID name collisions. Auto-discovery filters or missing CONNECT privilege do not hide rows visible in the progress views.
  • Container trust bundle: both scratch image build paths include the system CA bundle and license, allowing public-CA TLS verification out of the box. Private CAs still require a mounted certificate and sslrootcert; default TLS mode is unchanged.
  • Dependencies and release checks: move YAML from v3 to v4 while keeping existing collector configuration syntax, and update Prometheus common/procfs, golang.org/x/net, and related dependencies. CI validates container file/TLS behavior and all three DEB architectures in addition to RPM compatibility and checksums.
  • Aligned metric help text: clarify I/O byte vs operation counts, completed checkpoints, VACUUM dead-tuple memory, and CLUSTER progress. SQL metric names, label keys, types, and units are unchanged on the same PostgreSQL version.

Upgrade Notes

  1. Upgrade configuration and binary together. Merge the updated pg_exporter.yml or split YAML files; package upgrades keep local config files. Replacing only the binary does not apply the progress SQL fix. The default bundle remains 58 YAML files, 96 branches, 59 namespaces, and 460 distinct metric definitions, including disabled collectors and two unexpanded histograms.
  2. Review progress-label consumers. Cross-database relname values can change from an incorrect local name to a numeric OID, creating new time series; keep datname and pid in panels. Current-database and shared-catalog relation names remain readable.
  3. Choose the right health signal. /up and role endpoints reflect the latest health probe; pg_up reflects primary-target scrapes, including fatal collector failures. Inspect query and server metrics for non-fatal and child-database errors. --disable-intro suppresses all built-in metrics, including pg_up, while keeping HTTP health checks active.
  4. Account for the PgBouncer probe connection. The PgBouncer pool limit increases from one connection to two. PostgreSQL remains three on the main target and one per discovered database.
  5. Keep positive timeouts on fatal collectors. Canceling a negative-timeout fatal query caches a failure under the normal TTL. Later active scrapes can count that cached failure and report pg_up 0 until a refresh succeeds. Zero TTL or --disable-cache still forces refresh on every scrape.
  6. Review concurrency and budgets. Excess concurrent scrapes or interrupted scrapes can return 503. An already started bounded collector can overrun the request budget by roughly its own timeout; network stalls can extend longer, and neither deadline is a hard wall-clock cap. Configure a sensible connect_timeout in the DSN for connection handshakes.

A real failure that overlaps request cancellation can be omitted from the two round error counters because classification checks both scrape error and request context; query-level failure counters remain visible. If the first scrape is interrupted before precheck succeeds, pg_up stays 0 until a later scrape recovers. Failure TTL, reload, and immediate SIGTERM exit semantics are unchanged; this release adds no background refresh or graceful shutdown.

When upgrading from v1.4.1 or earlier, also apply the v1.5.0 migration notes, including subscription labels, receiver state mappings, and the PostgreSQL 10–13 monitoring grant. For the full runtime contract, see Compatibility, HTTP API, and Scrape Lifetime.

Verification Scope

Release verification covered the full race test suite, both HTTP mux modes, module and generated-config consistency, static analysis, six-platform builds, container TLS/file checks, and package validation. Three cancellation regressions also passed 200 consecutive race-enabled iterations; a negative control with the interruption fix removed failed earlier. On PostgreSQL 18.6, a client disconnecting during a 0.8s bounded fatal query left both round error counters at 0, and the next scrape returned pg_up 1 with cached metrics without re-running SQL.

Local acceptance against the release artifacts also covered PostgreSQL 9.2–9.6 (legacy config), 10–18 and 19 RC1 (default config), and PgBouncer 1.26.1. Linux amd64/arm64/ppc64le tarballs and RPM/DEB packages passed runtime and install checks; ARM64 package upgrades from 1.5.0 preserved local configuration. Docker Hub 1.6.0 and latest point to the same amd64/arm64 multi-arch manifest; pulled public images passed CA, file, and TLS checks, and their binaries matched the corresponding release tarballs byte-for-byte. All 24 functional test groups passed on Darwin ARM64, including HTTPS auth, reload overlap, standby promotion, and disconnect recovery. Windows and Intel macOS received static binary checks only; container package tests did not exercise real systemd service startup.

Progress SQL branches were verified with the monitoring role on PostgreSQL 12, 17, and 18, with supplementary shared-catalog cases and a live cross-database VACUUM checked on 18.6. These are bounded acceptance results, not a complete re-audit of every PostgreSQL version, extension, dashboard, or production workload. Composite, Patroni, pgBackRest, and PostgreSQL-log components remain on the separate snort line and are not part of v1.6.0.

SHA-256 Checksums

SHA256 checksums

Download asset
FileChecksum
pg-exporter-1.6.0-1.aarch64.rpm Linuxarm64SHA-256dd81e485377fd9bfead1b3e8000a145eb89d1c914becffaa3588cafc67731ed9
pg-exporter-1.6.0-1.ppc64le.rpm LinuxSHA-256413f64b25feb6202bf7cf70f10d0a73527c42767a2cc2bef37beef6d33ab48ae
pg-exporter-1.6.0-1.x86_64.rpm Linuxamd64SHA-256c25e57077f916a83993263eb0009959bbafe183fb3da4f81169629dfdbd7c64a
pg-exporter_1.6.0-1_amd64.deb Linuxamd64SHA-25646f03078e7e74430c34d3650b48cecacc55e011c6bcecde4f3ef555076f917b3
pg-exporter_1.6.0-1_arm64.deb Linuxarm64SHA-256d24dea8ee5774f28a8e4c5e9c9977b07d80b6e1c4d5a86a7b7802cc5d6d02a0f
pg-exporter_1.6.0-1_ppc64le.deb LinuxSHA-2565cc839bc5f9d551559984442fcd24305e3113688dc2d92d437ed5421683e3ae0
pg_exporter-1.6.0.darwin-amd64.tar.gz macOSamd64SHA-256ddefa112d810bf5ae8acc0eeb9edc23b44609ecd577a75df8f5c2321f81fea47
pg_exporter-1.6.0.darwin-arm64.tar.gz macOSarm64SHA-256a62d9474d091ac906a5fcd1898ffce599eaf74fb7c93800caa85b6c190d64d85
pg_exporter-1.6.0.linux-amd64.tar.gz Linuxamd64SHA-256296a26bf83acd7024f4de8fdeac0ee31baffa01e3153cf5c694e90ed8268719a
pg_exporter-1.6.0.linux-arm64.tar.gz Linuxarm64SHA-256ea6d1dbe0820d599e81ed702e128b4fe4a557e2afb5b5c157de222576c1d7ce7
pg_exporter-1.6.0.linux-ppc64le.tar.gz LinuxSHA-256b720183a3c4d35d20d683bc6ba998e5eddcb1f76e5721788829aa56c2cd7155a
pg_exporter-1.6.0.windows-amd64.tar.gz Windowsamd64SHA-25629909ef65af96f1da5e7258c7b9025c85ad1dca63596c9fba8b85b55e006bb25

GitHub release · SHA256 checksums · Full changelog · Complete collector reference

v1.5.0

Release date: 2026-10-23. This release improves connection security, collection accuracy, and runtime state consistency, and upgrades the build toolchain to Go 1.27.3.

Fixes and Improvements

  • Validate PostgreSQL URLs and query parameters strictly. Reject malformed escapes and parameter names containing whitespace or =. Safe diagnostics prevent malformed connection strings from leaking passwords into logs or silently discarding explicit TLS settings. An empty or whitespace-only file selected through PG_EXPORTER_URL_FILE now prevents startup.
  • Resolve database identities with lib/pq. Auto-discovery removes conflicting dbname / database query parameters when replacing a database name and preserves special characters, fixing duplicate collection and HTTP 500 responses caused by duplicate metrics.
  • Generate each health response’s HTTP status and body from one atomic state snapshot, fixing contradictory responses during concurrent state transitions. Health checks still use background cached state.
  • Replan after a successful precheck detects changes to the username, schemas, or extensions. Unchanged metadata preserves plans and caches. Adding or removing a schema or extension no longer requires manual reload.
  • Reject NaN, infinities, and overflowing TTLs or positive timeouts during configuration loading. Preserve the existing meanings of zero TTL (disable caching), zero timeout (use the default), and finite negative timeout (disable the deadline).
  • Verify at startup that the active HTTP mux routes the metrics path to the metrics handler. Reject escaped paths that would return the landing page or a redirect under the legacy mux.
  • Add the owning database’s datname label to pg_sub_*, preventing collisions between identically named subscriptions in different databases. Correct pg_recv_state codes in the current and legacy bundles, and fix receiver address extraction on PostgreSQL 9.6.
  • Clarify pg_origin permissions, the table scope of pg_pubrel_count, synchronization states and PostgreSQL 19 sequence semantics in pg_subrel_count, and the pg_backend description.

Metric and dashboard compatibility

Compared with v1.4.1 on the same PostgreSQL version, v1.5.0 does not add, remove, or rename bundled SQL metric names. Types and units remain unchanged, but labels and state mappings do change. PostgreSQL 19 support first shipped in v1.3.0; upgrading the database can also change the selected SQL branch and a metric’s meaning.

ScopeMetricsCompatibility action
v1.5.0 configurationpg_sub_*Adds datname to every sample. Keep database and subscription identity in joins and aggregations; new label sets create new time series.
v1.5.0 configurationpg_recv_stateReal receiver states starting, waiting, restarting, and stopped now map to 6–9 instead of -1. Update value mappings and state alerts; codes 1–3 are reserved.
PG18 → PG19Existing PG18 metric namesNone are removed or renamed by the PG19 branches in this bundle. This does not guarantee unchanged semantics or labels from PostgreSQL itself.
PG19pg_sub_sync_error_countKeeps the name but becomes the sum of table and sequence synchronization errors. For table-only alerts, use pg_sub_sync_table_error_count; pg_sub_sync_seq_error_count reports the sequence component. Do not double-count the components and their sum.
PG19pg_sub_has_worker, pg_sub_reset_time, pg_sub_confl_*Adds worker presence, reset time, and eight conflict counters. The subscription row can remain without an apply worker; metric presence alone is not a worker-health check.
PG19pg_subrel_countIncludes sequences as well as tables; pg_pubrel_count still counts tables only. Review panel labels and count comparisons.
PG19pg_wal_fpi_bytes, pg_lock_stat_*, pg_recovery_state_*, pg_vacuum_score_*Additive metrics. Recovery state is replica-only; autovacuum scores are primary-only. Existing WAL, lock-distribution, and recovery families remain.

Users upgrading from PG17 or earlier must also migrate older names: checkpoint metrics left pg_bgwriter_* in PG17, and pg_wal_write, pg_wal_sync, pg_wal_write_time, and pg_wal_sync_time are absent from PG18 onward. The full compatibility guide lists each replacement, label/aggregation differences, and mixed-version PromQL.

Before rollout, evaluate the actual dashboard and alert expressions and test missing-series input. A successful scrape does not ensure every expected metric exists; an empty alert expression can silently stop firing. The missing-metric checks include a per-target rule and explain when absence is expected. The full PG19 metric table links to the tagged collector definitions; PostgreSQL validation remains scoped to 19 RC1.

Upgrade Notes

  • On PostgreSQL 10–13, an administrator must run GRANT SELECT (oid) ON pg_catalog.pg_subscription TO monitor; in the exporter’s main connection database, substituting the actual monitoring role. This does not expose subconninfo. PostgreSQL 14+ needs no extra grant under standard catalog ACLs.
  • The new datname label on pg_sub_* creates new time series. Review PromQL joins, aggregations, and alerts that match these labels. The pg_sub_id gauge is retained.
  • pg_recv_state uses the following codes; 1–3 remain reserved. No receiver row means no sample. PostgreSQL 9.6 still hides receiver details from ordinary monitoring roles, resulting in an unknown state; the exporter does not expand database privileges.
StateCodeStateCode
streaming0starting6
stopping4waiting7
connecting (PG19+)5restarting8
unknown / NULL-1stopped9
  • Upgrade both the binary and collector configuration. Packages preserve local configuration changes: merge the new pg_exporter.yml, then check query error counters in /metrics. HTTP 200 alone does not establish a successful scrape.
  • Reloading empty YAML still clears collectors, and directory loading still permits valid files to load when others fail. SIGTERM retains immediate process termination; it does not wait for active scrapes to complete.

Toolchain and Validation

Retain lib/pq 1.12.3 and upgrade Prometheus client_golang to 1.25.0, common to 0.72.1, and exporter-toolkit to 0.20.0. YAML uses go.yaml.in/yaml/v3 3.0.5. The PostgreSQL driver remains lib/pq.

The default bundle still contains 58 YAML files, 96 branches, 59 namespaces, and 460 distinct metric definitions, including two unexpanded histograms. Validation covered non-superuser collection on PostgreSQL 9.1–9.6, 10–18, 19 RC1, and PgBouncer 1.26.1; physical standby promotion, reloads, disconnect recovery, races, both HTTP mux modes, six-platform builds, ARM64 RPM/DEB installation, and Docker images. PostgreSQL 19 testing used RC1; this does not cover every extension or production workload.

Go and Dependency Security Updates

Go 1.27.3 adds a blocklist for untrusted intermediate certificates in crypto/x509, addressing CVE-2026-111943. It also includes security fixes accumulated since the previous Go 1.26.5 build, including TLS issues CVE-2026-56862 and CVE-2026-97031, HTTP issues CVE-2026-56853 and CVE-2026-94439, and template, ASN.1, and multipart fixes. See the complete upstream scope in the Go 1.26.6, Go 1.27.2, and Go 1.27.3 announcements.

golang.org/x/net moves from 0.57.0 to 0.61.0, including five HTTP/2 fixes introduced in 0.60.0:

CVEFix
CVE-2026-78659Memory amplification through Trailer headers
CVE-2026-78669CPU consumption through window updates
CVE-2026-78663Duplicate flow-control credit refunds
CVE-2026-97032HPACK encoder race and crash
CVE-2026-78660Malformed framing response headers

x/crypto 0.58.0 also crosses the fixes for SSH issues CVE-2026-56854, CVE-2026-56855, and CVE-2026-78662. x/text 0.43.0 includes the precis fix CVE-2026-56851. The exporter does not import these SSH/precis packages; these are dependency-version updates, not confirmed exporter runtime vulnerabilities.

Comparative govulncheck runs on 2026-10-23 found no known symbol-level or imported-package-level vulnerabilities in the new candidate for Darwin, Linux, or Windows. The unimported OpenPGP package retains a module-level advisory, GO-2026-5932. Static symbol matches are not exploit reproductions, and including upstream fixes does not establish that every issue was exploitable in the exporter. Other dependency upgrades are maintenance updates. Install the rebuilt release binary; upgrading Go on the host does not change an existing binary.

For the full CVE table, first fixed versions, and scan levels, see the security update verification.

SHA-256 Checksums

SHA256 checksums

Download asset
FileChecksum
pg-exporter-1.5.0-1.aarch64.rpm Linuxarm64SHA-2564cb1dfbbc6d22101d43e0841f6d5d86042a15f3894bd6e935151a1b94b94b980
pg-exporter-1.5.0-1.ppc64le.rpm LinuxSHA-256c7efed8ab2062b873c87664987d73b8ff37fde89943b98a7f1967aef7961f7eb
pg-exporter-1.5.0-1.x86_64.rpm Linuxamd64SHA-2566788c7cbb83e4708199f00a1ddf8057f74ba3606e28e3aa26eeaf1a453a1e1b3
pg-exporter_1.5.0-1_amd64.deb Linuxamd64SHA-25691f705bbeba67a6a4c4e6a4595efb3d214f787d38d7e310c3121a594ecdce28f
pg-exporter_1.5.0-1_arm64.deb Linuxarm64SHA-25675dd27cdd734a84d703d594d0b4173d21ff302c95cb04320da528f8789f147bd
pg-exporter_1.5.0-1_ppc64le.deb LinuxSHA-256f41acf7693172d5e843df2c5e49e5173e74f9519f84b5453b0dcfa834c1efaf1
pg_exporter-1.5.0.darwin-amd64.tar.gz macOSamd64SHA-256f3e5d03d3c3ca7df5e50e017e1c18ec78ccdc099f610296f674349acc1466975
pg_exporter-1.5.0.darwin-arm64.tar.gz macOSarm64SHA-2563fb47e285c2700227b0437c827fdbf0d87a93e24befb5e94f439082073700e8d
pg_exporter-1.5.0.linux-amd64.tar.gz Linuxamd64SHA-256e372f6defb844b4bfbe3286b40dba3d4aae2ce72c4bed9980e3b9a56507aef56
pg_exporter-1.5.0.linux-arm64.tar.gz Linuxarm64SHA-25619f34db9e034d1437791af52676cf32e60a669d4a5036e0cc3efbe14efb61cde
pg_exporter-1.5.0.linux-ppc64le.tar.gz LinuxSHA-256aef7e910480656ddc744c4d6f1cdb3448299e6c63a469d9110fdf280d0c15ac2
pg_exporter-1.5.0.windows-amd64.tar.gz Windowsamd64SHA-256cf39b3ecfeeac7d088e348ab24e717e600e3f61c98611b0815fb18fef1db1d9f

GitHub release · SHA256 checksums · Full changelog · Complete collector reference

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.

Checksums

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

Download asset
FileChecksum
pg-exporter-1.4.1-1.aarch64.rpm Linuxarm64SHA-2567648f1852f12a17c5ecc9c2f6aed1888f443d6e650c5001f9c8a05d7e4822f13
pg-exporter-1.4.1-1.ppc64le.rpm LinuxSHA-25609037731e2d4bd22dcabb9a386f381c67a782a05a0f9ed54517312d7ea8e6631
pg-exporter-1.4.1-1.x86_64.rpm Linuxamd64SHA-2568dbf85ff6adc4b46b225b3a1e3be5a4a61130118eabee499865a88d04a3e1a93
pg-exporter_1.4.1-1_amd64.deb Linuxamd64SHA-256cbe06eb161421a160d07b8c757864919d2ce1717b402630906235c471e411f38
pg-exporter_1.4.1-1_arm64.deb Linuxarm64SHA-25636bc07ef2e3189b2acef06cf602ec9800ad6dc8b619ab5b2bfa5f900d9975cff
pg-exporter_1.4.1-1_ppc64le.deb LinuxSHA-2568228e6a9b73d68aafedf6b4ed795636b9528c254052709086de4fa5084707aad
pg_exporter-1.4.1.darwin-amd64.tar.gz macOSamd64SHA-256e6de4c890af8d1c54b4a597e9fd02329e9caa543604c8406270a7a3c842d76f4
pg_exporter-1.4.1.darwin-arm64.tar.gz macOSarm64SHA-2566fe0b19398983587fbe5e9a31dd8de0aeaf03b6b91a6fe22fc71f63ba703a79f
pg_exporter-1.4.1.linux-amd64.tar.gz Linuxamd64SHA-256f2f952dbcf1ae09027bcee4ea4921d2b34f9f58ffbc7e3a2d42113f2cc94a340
pg_exporter-1.4.1.linux-arm64.tar.gz Linuxarm64SHA-256e111974a12175d5f65c4ee0fb888604e6b343d893476ef4e88264a4c9601e8b4
pg_exporter-1.4.1.linux-ppc64le.tar.gz LinuxSHA-2567b8679de0d58373f5f570c0560125fb465f91e7a4d71223699e81c9ca6b84469
pg_exporter-1.4.1.windows-amd64.tar.gz Windowsamd64SHA-25693c0231fbd3eae45604b0c723cf413b2bec5e0cfa652912b12fdf400f1761db4

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

Download asset
FileChecksum
pg-exporter_1.4.0-1_amd64.deb Linuxamd64SHA-256c6af4ae62e13f518539a6d0b3ce86ff9f7acdb567a4f0f86c6f47563574da724
pg-exporter_1.4.0-1_arm64.deb Linuxarm64SHA-256ff0360f61982ed627d1b1f93281a0ba66da9d077672f0c214e19522df01e40d6
pg-exporter_1.4.0-1_ppc64le.deb LinuxSHA-2564fbadd4e9d918c9bc8e63975378e49375b0ff897d6b8a0f78799538b13dd68a1
pg_exporter-1.4.0-1.aarch64.rpm Linuxarm64SHA-2565ce106d27fffa77c39fea9bf7cbc60f4328df3d926fef025bfdd082eb6d743fd
pg_exporter-1.4.0-1.ppc64le.rpm LinuxSHA-256870b434e802e0039f10e1e3583c28a1fd83db4363a4608e1fab7f375f6d30600
pg_exporter-1.4.0-1.x86_64.rpm Linuxamd64SHA-256c550d16ce3f9276948a4d44174e11716fc5e85e31e8788ea106a57cfbabd8488
pg_exporter-1.4.0.darwin-amd64.tar.gz macOSamd64SHA-25611a34e531ac5d6d378b91e768f575525389141a6860afabd0cc9f2d853f06749
pg_exporter-1.4.0.darwin-arm64.tar.gz macOSarm64SHA-25649d8d3a5932602f433c4ef681ed12007da1cbc11b5ee0f9d7b4dc2d0dff8e26e
pg_exporter-1.4.0.linux-amd64.tar.gz Linuxamd64SHA-256113dfe70d4f780a456c05ca6b731f96c1013bf35ecb87d75c443fe2bac7e333b
pg_exporter-1.4.0.linux-arm64.tar.gz Linuxarm64SHA-25668b4630ab39943658a8aff135990896a5ccf56c8a992e5982d572c78ef822e18
pg_exporter-1.4.0.linux-ppc64le.tar.gz LinuxSHA-25672710625e5658c941b48f7becba9a86491852cea5469240328292838d9ed0979
pg_exporter-1.4.0.windows-amd64.tar.gz Windowsamd64SHA-25614a0cf6ffa04c7e54c1d5aa5b37fe4bea1429c1d1e7cce89e9dd805c4a29db0b

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

Download asset
FileChecksum
pg-exporter_1.3.0-1_amd64.deb Linuxamd64SHA-256dfc6d517300687a382557e6d77af1ecb513bdde2e961d01ca46efa008ae15569
pg-exporter_1.3.0-1_arm64.deb Linuxarm64SHA-2563d2ff642d0bb3657b28eb7c4b30bacc8ef9e4cbd057c870e6ec6817b47ac8092
pg-exporter_1.3.0-1_ppc64le.deb LinuxSHA-2564cfe043eb193780515a1e00ab93250dd44ca0728b35cb037ed165c70c89b6b5a
pg_exporter-1.3.0-1.aarch64.rpm Linuxarm64SHA-2563ae4f8c554242ae52c4ba0fa07a9d95b702f72938ce55e8456dd97242cc46faf
pg_exporter-1.3.0-1.ppc64le.rpm LinuxSHA-25671a0023383170b4ef3c243d9bf08d530b819fa891fa784e87c74b2a55cb426ec
pg_exporter-1.3.0-1.x86_64.rpm Linuxamd64SHA-256316a97ccb2df9a02de99dda33826857ec32bbd6fd874ffb950625bc064d62496
pg_exporter-1.3.0.darwin-amd64.tar.gz macOSamd64SHA-2564ab312f27f0ded7f0ff5591866a86311d13041fef3a015e92f44fcf4a2284ccd
pg_exporter-1.3.0.darwin-arm64.tar.gz macOSarm64SHA-2562b20eb7b46c0790a8524f1c00a22ab57739bd60fd89ee947f6c2ba14e6a0d6bb
pg_exporter-1.3.0.linux-amd64.tar.gz Linuxamd64SHA-2567a2a8ce818f30260d1e7267d0b9e1fd5b3cbd569d55ad184fc9d6fb3801f3ad7
pg_exporter-1.3.0.linux-arm64.tar.gz Linuxarm64SHA-256696619d19efbcf33f4afbae9748e72897289d2b7f772509cd6d465c9e818066d
pg_exporter-1.3.0.linux-ppc64le.tar.gz LinuxSHA-2560c16ac4a912f328be90e973b5123a272c2747759be9f56bacb5542653226475e
pg_exporter-1.3.0.windows-amd64.tar.gz Windowsamd64SHA-256aa3724f4e8aeb732de18b7cb416283cbc2e94b9f511ec4b94e703792e8e8b10d

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

Download asset
FileChecksum
pg-exporter_1.2.2-1_amd64.deb Linuxamd64SHA-256273dfd45ac367f71044998d19171ee27d7deb094ec9410d4b31aef7caacfdcc6
pg-exporter_1.2.2-1_arm64.deb Linuxarm64SHA-2565e83c8448ee6350bec96ab95550df439a129c6700e5c9c7d0f9411aa9c2e7f40
pg-exporter_1.2.2-1_ppc64le.deb LinuxSHA-25697bb804bd1018c111708df9118561421d2cc51bd47d031b6d1f12cf1c988a3b2
pg_exporter-1.2.2-1.aarch64.rpm Linuxarm64SHA-256b2f76799b21aba02b6bf5b6e71bf7ae2cf4487ad8817d53aad92f1d710c00120
pg_exporter-1.2.2-1.ppc64le.rpm LinuxSHA-256f0ab38907bc87a9634c22911d8a0501634d58ce34020c0952dd49281a06787e6
pg_exporter-1.2.2-1.x86_64.rpm Linuxamd64SHA-2562000593d9d6732f3e03a43e291bc4e2368d2ecea125a2744dc533a030f51c800
pg_exporter-1.2.2.darwin-amd64.tar.gz macOSamd64SHA-256e8a71704eb6957beaebd8ecaf83479e44db4a09bd9dc95c32f7b617f141b0386
pg_exporter-1.2.2.darwin-arm64.tar.gz macOSarm64SHA-256e648d9444f9a5f3ee49b82bcbbb459eefd73307c789f24f0d5238dbe1bcfec9c
pg_exporter-1.2.2.linux-amd64.tar.gz Linuxamd64SHA-256f278aba93d09b2a47aeef66898e770cacfdbc046eab0ba02de29f7c0261d9ede
pg_exporter-1.2.2.linux-arm64.tar.gz Linuxarm64SHA-256bbeef56452643b8eb6bf9bb5baf113ab2c38177c06f8e1d008e63cce82260801
pg_exporter-1.2.2.linux-ppc64le.tar.gz LinuxSHA-256ad2385278ec6060fef2f7db7873c025f56f5c55048b51815cb4195486ca9dbe2
pg_exporter-1.2.2.windows-amd64.tar.gz Windowsamd64SHA-2562ac53298058f09c5569464f918396f13d3a9efebec00296d89497e97ea74caf4

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

Download asset
FileChecksum
pg-exporter_1.2.1-1_amd64.deb Linuxamd64SHA-2562cbe7a78a0dde8a6155a543232af883de6623531c9f6ea0951ddc30dc7514649
pg-exporter_1.2.1-1_arm64.deb Linuxarm64SHA-256e70e09974ad52ba607b176b63c300610e37f44fe67d249aa9ef364bd58352585
pg-exporter_1.2.1-1_ppc64le.deb LinuxSHA-2564e6c7fae85e7fe2e62c3d66c388b5f3db57b5e95e85f43ce648d21b792d83d87
pg_exporter-1.2.1-1.aarch64.rpm Linuxarm64SHA-25630103629e8c5c1ee5589addadb37fcb07b43179c8a19f80c016a0ed8d7ac2a47
pg_exporter-1.2.1-1.ppc64le.rpm LinuxSHA-25601b4dd32b20bca8612f71f0edf3557dfa92fc85f669d3260f627d34ce102b517
pg_exporter-1.2.1-1.x86_64.rpm Linuxamd64SHA-2565afb4f14aa71b256cdfc93d6cc6da8a7052427d6f1c1b71900bf2593b196de50
pg_exporter-1.2.1.darwin-amd64.tar.gz macOSamd64SHA-25645e71c6017beffabf2873841d374b5de40eb499dd768d6db1208d7cc6295bcf5
pg_exporter-1.2.1.darwin-arm64.tar.gz macOSarm64SHA-256d3035cc6a023fe1bad5443a7c1d5c8189b3d807d165f131f88566b5c35476259
pg_exporter-1.2.1.linux-amd64.tar.gz Linuxamd64SHA-25614d3f83de4377e5363611d2ae4eef9470a85d7518784c06b8a8c0f63b6e0a340
pg_exporter-1.2.1.linux-arm64.tar.gz Linuxarm64SHA-25671082081e7aaf1cf15c941c310d03da49cf9971205274aad7dae21a126bc4fe1
pg_exporter-1.2.1.linux-ppc64le.tar.gz LinuxSHA-256cba30919b8d2945be199a4a346eb2891c88fd7a1d6c3482c1006442f4f6109e7
pg_exporter-1.2.1.windows-amd64.tar.gz Windowsamd64SHA-2566fe528a242f0bbd3b89cd8b2697f48905b5c4b1398abfb3305193808c01738e9

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

Download asset
FileChecksum
pg-exporter_1.2.0-1_amd64.deb Linuxamd64SHA-25626e7a052e730b412bbbe5f49846f951b89650f1f95c2466d5d486923f0825f64
pg-exporter_1.2.0-1_arm64.deb Linuxarm64SHA-2564ec219135c49708d010af7b8a7553b8008f630574e1d4cfc7642fbf951eefafe
pg-exporter_1.2.0-1_ppc64le.deb LinuxSHA-2565b2cc00e2c3e2ffd9eb0ab1a4f5e937dd68f3a69a14423a74d4de3d7cf29283e
pg_exporter-1.2.0-1.aarch64.rpm Linuxarm64SHA-256d536d41a92e8aa85ae3935715d1bf0463208b1e614eae73543f1472ca8a7e0d4
pg_exporter-1.2.0-1.ppc64le.rpm LinuxSHA-256b7a1daa225f8ca4de6d227e6004330589295d924accd221892ebe14f191fe35c
pg_exporter-1.2.0-1.x86_64.rpm Linuxamd64SHA-25628bf7d85862510675c64ff5181d216c6a068a23ffa56dc4bb9e6b82165ff99b5
pg_exporter-1.2.0.darwin-amd64.tar.gz macOSamd64SHA-25651c3b3d18089d888a54a6b3e7ecb0620dc0da04c81471a0b7aaa88c1677ddb8c
pg_exporter-1.2.0.darwin-arm64.tar.gz macOSarm64SHA-2563ba1c7adea9c926afd3054ba18cc43e665e420a495bfcfd2248242c49a67b077
pg_exporter-1.2.0.linux-amd64.tar.gz Linuxamd64SHA-2569e1ec6c15e6b2aaadbe27a27053ee1ec289bdd012c19ca6371de738fa5f8843e
pg_exporter-1.2.0.linux-arm64.tar.gz Linuxarm64SHA-2569e18849693ccda313979db0a230cb81acfe4199364feb6ce3e72d1a89fbfb809
pg_exporter-1.2.0.linux-ppc64le.tar.gz LinuxSHA-2566e28489685d0bd1fdabcb71474f64f559ade199b871666954323bae9dc01465f
pg_exporter-1.2.0.windows-amd64.tar.gz Windowsamd64SHA-2569e9beac619fe2c614a77bc3334bc4b80df9db355bf95845eb4b11674ddad52d9

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

Download asset
FileChecksum
pg-exporter_1.1.2-1_amd64.deb Linuxamd64SHA-2568cddd57a843914a3145a80a3220bc875047b9bcac0664357c01ba86485436236
pg-exporter_1.1.2-1_arm64.deb Linuxarm64SHA-256f5b25a8ae5c022867a54c17ba1c6493eba20dcb292340460390289336df24f04
pg-exporter_1.1.2-1_ppc64le.deb LinuxSHA-2564da2c287f6717681b25befda0d59a89b9d1b258281ce94f3a6bc21d02f70c83c
pg_exporter-1.1.2-1.aarch64.rpm Linuxarm64SHA-256b26355f3c1a5b8a147291a51e2d7ada204deed6d52877c146a8b3e499defa5e8
pg_exporter-1.1.2-1.ppc64le.rpm LinuxSHA-25642ef89716ba99dd918b0e9c77ef3236129d613f68bb8ae5929668a5a2596cca5
pg_exporter-1.1.2-1.x86_64.rpm Linuxamd64SHA-256a8f4a2d5c7b6701c7bac788a7ed7183b6c4b74a334326cd389f3a695fb77675d
pg_exporter-1.1.2.darwin-amd64.tar.gz macOSamd64SHA-256775f5ea3188a6acb1327c001c4ba9a0651424c3bb37d800e6f67972c904c4750
pg_exporter-1.1.2.darwin-arm64.tar.gz macOSarm64SHA-2567f2bbcc2db1e16dc78c3edd8e67e20e4ec81f2972c8c37135cba6f6afbf91003
pg_exporter-1.1.2.linux-amd64.tar.gz Linuxamd64SHA-25633c34b1f9ef6b6e7615f241a95059a8137a2337a454930b668180a9329d12b98
pg_exporter-1.1.2.linux-arm64.tar.gz Linuxarm64SHA-2562b91a5818d780e38692ab6446cacb496695e67388676c18012be582e8ddfbdd8
pg_exporter-1.1.2.linux-ppc64le.tar.gz LinuxSHA-256adcb5f229f4a5d641f6430b9a2dfb0377a2e4310efad242730867d6cdf5e27ee
pg_exporter-1.1.2.windows-amd64.tar.gz Windowsamd64SHA-25690b7c7e4b2b94936b5faa3cf2d35509b62ebc0d60b3afe1abaaf03efcd415a4a

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

Download asset
FileChecksum
pg-exporter_1.1.1-1_amd64.deb Linuxamd64SHA-256fd5ee96511676fc11b975115a4870ed0c811056519f79ad7f24ab7ec538fa278
pg-exporter_1.1.1-1_arm64.deb Linuxarm64SHA-256b90a08d16a6e4707d82f8f3ae282cb76acb331de607e7544532fd0b774b7aa27
pg-exporter_1.1.1-1_ppc64le.deb LinuxSHA-256163955f59a71da48901ffa26bb2f2db0712d31d8aeb1ab3fa463683f719a6d3a
pg_exporter-1.1.1-1.aarch64.rpm Linuxarm64SHA-256cf4f8bc12bb8a2d1e55553f891fd31c43324e4348249727972eb44f82cd4e6c8
pg_exporter-1.1.1-1.ppc64le.rpm LinuxSHA-2565a425b2f61f308b32f2d107372830c34eb685bfb312ee787f11877a20f1c4a2e
pg_exporter-1.1.1-1.x86_64.rpm Linuxamd64SHA-25623606ccea565368971ac2e7f39766455b507021f09457bcf61db13cb10501a16
pg_exporter-1.1.1.darwin-amd64.tar.gz macOSamd64SHA-256ce74624eba92573318f50764cee4f355fa1f35697d209f70a4240f8f9d976188
pg_exporter-1.1.1.darwin-arm64.tar.gz macOSarm64SHA-25635fba12521dbdcc54a3792278ed4822e4ca9e951665b5e53dff7c2a0f7014ae3
pg_exporter-1.1.1.linux-amd64.tar.gz Linuxamd64SHA-2567699bdef15dd306289645beee8d40a123ca75dc988e46d89cdd75a1c1f650bef
pg_exporter-1.1.1.linux-arm64.tar.gz Linuxarm64SHA-256f4baba59d27a8eb67f0c5209fed7b9f00f78db796e583cc3487701e7803671c6
pg_exporter-1.1.1.linux-ppc64le.tar.gz LinuxSHA-256810c3817c27358fa667714f8bfe8d52840a7ea010035e29547919ccb7c9fa781
pg_exporter-1.1.1.windows-amd64.tar.gz Windowsamd64SHA-2563f6df693b3eb92fdaeaeccf99ea7e5977b2c65028a4f00bdfabbc0405b9f5f93

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

Download asset
FileChecksum
pg-exporter_1.1.0-1_amd64.deb Linuxamd64SHA-2569c65f43e76213bb8a49d1eab2c76a27d9ab694e67bc79f0ad12769ea362b5ca2
pg-exporter_1.1.0-1_arm64.deb Linuxarm64SHA-256bcd2cacb4febc5fb92f9eda8e733c161c8c6721416e16ec91a773503241c972d
pg-exporter_1.1.0-1_ppc64le.deb LinuxSHA-2562c9d4a9cb06d07af0b6dd9dd6e568af073dc9f6775abde63b45f0aae34d171b1
pg_exporter-1.1.0-1.aarch64.rpm Linuxarm64SHA-2562934ab5b0fb16dca5a96ec1e8f230e32c72b30ca076b5e5ddf8ec553c821f7b8
pg_exporter-1.1.0-1.ppc64le.rpm LinuxSHA-2563c9955f31ba93532cc7f95ff60b0658f4b6eca6a827710e2f70c0716b34eab43
pg_exporter-1.1.0-1.x86_64.rpm Linuxamd64SHA-2569fdefbd8e7660dcb130207901a27762e0a381857ba8cf12b63184744f92dea05
pg_exporter-1.1.0.darwin-amd64.tar.gz macOSamd64SHA-2567159002016754309e0ed625a9a48049d21177883fa11d1e448eb7655ceb690cc
pg_exporter-1.1.0.darwin-arm64.tar.gz macOSarm64SHA-2567d55ac5cda0b1fd8ffbd5e76b9c1c1784ac8e353104a206caaadce89adda6d65
pg_exporter-1.1.0.linux-amd64.tar.gz Linuxamd64SHA-2568211ec24277554b9b1a36920d7865153e21c2621031d3d08f22d94cdd2ddf02f
pg_exporter-1.1.0.linux-arm64.tar.gz Linuxarm64SHA-256d17ab7f9bf04442e642483d432d005d25bb62e0c9caa73cb7e69ee19eb89b3ae
pg_exporter-1.1.0.linux-ppc64le.tar.gz LinuxSHA-256c074aeb345cc30f7b6e16aa153ae3d9a12789e4425987590c3fd77c4e68a40b6
pg_exporter-1.1.0.windows-amd64.tar.gz Windowsamd64SHA-25613d653e2abb023ce9526bdc2815135b82f49c044d237030f3f56b09fb016fcb7

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

Download asset
FileChecksum
pg-exporter_1.0.3-1_amd64.deb Linuxamd64SHA-2567efa1a77dfd5b94813c32c7ac015b1d479b1f04fb958f6b1ed5af333e354d015
pg-exporter_1.0.3-1_arm64.deb Linuxarm64SHA-25641e18bf18eba2ab90ac371bfb46e9152da9fe628ebd8e26766cac08325eb3b07
pg-exporter_1.0.3-1_ppc64le.deb LinuxSHA-2567da8ed738d254c120d42aa51d6137f84e7f4e3188bc764d4f9a1438220363a43
pg_exporter-1.0.3-1.aarch64.rpm Linuxarm64SHA-256a214b555981156da7b7d248b1f728f8ac88a07ac8f77a66c5d8e43b40670d6b4
pg_exporter-1.0.3-1.ppc64le.rpm LinuxSHA-256d876fc66e208612ebffe3c43dabce88b088d915f92584260d710b85a3a131413
pg_exporter-1.0.3-1.x86_64.rpm Linuxamd64SHA-25675f62d314fec50c836c534996c884d25ecea77810ab33e7ba0e9c4b783e775b4
pg_exporter-1.0.3.darwin-amd64.tar.gz macOSamd64SHA-25647829a19707284bcee1b8dc47cc7d0172398bb533e6b4043950f787486712769
pg_exporter-1.0.3.darwin-arm64.tar.gz macOSarm64SHA-25638b6ccb72315cadea542b1f2a7b7022d0e8d48ffd4ab177bb69a0a909b99af6b
pg_exporter-1.0.3.linux-amd64.tar.gz Linuxamd64SHA-25636e8dff84d61a7593ff1fcec567ca4ffeaecd0be2f9eabd227ceac71b12a919a
pg_exporter-1.0.3.linux-arm64.tar.gz Linuxarm64SHA-2566477e8ef873773a09c4f39a29444f21b5b2c71e717e52ca425bcc8e8e5448791
pg_exporter-1.0.3.linux-ppc64le.tar.gz LinuxSHA-256a083b51ebed2b280e2eaa0f19558494e7fa6f122a0a86a1d117206fcd090820c
pg_exporter-1.0.3.windows-amd64.tar.gz Windowsamd64SHA-256a1f9b27b7190f478726d96f270a72d9dc4d3f2bcc3b0326b7c4a2607e62ea588

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

Download asset
FileChecksum
pg-exporter_1.0.2-1_amd64.deb Linuxamd64SHA-256683bf97f22173f2f2ec319a88e136939c2958a1f5ced4f4aa09a1357fc1c44c5
pg-exporter_1.0.2-1_arm64.deb Linuxarm64SHA-256f62d479a92be2d03211c162b8419f968cea87ceef5b1f25f2bcd390e0b72ccb5
pg-exporter_1.0.2-1_ppc64le.deb LinuxSHA-256e1bbfc5a4c1b93e6f92bc7adcb4364583ab763e76e156aa5c979d6d1040f4c7a
pg_exporter-1.0.2-1.aarch64.rpm Linuxarm64SHA-256f51d5b45448e6bbec3467d1d1dc049b1e16976f723af713c4262541ac55a039c
pg_exporter-1.0.2-1.ppc64le.rpm LinuxSHA-25618380011543674e4c48b2410266b41165974d780cbc8918fc562152ba623939e
pg_exporter-1.0.2-1.x86_64.rpm Linuxamd64SHA-256198372d894b9598c166a0e91ca36d3c9271cb65298415f63dbffcf6da611f2bb
pg_exporter-1.0.2.darwin-amd64.tar.gz macOSamd64SHA-256cbe7e07df6d180507c830cdab4cf86d40ccd62774723946307b5331d4270477d
pg_exporter-1.0.2.darwin-arm64.tar.gz macOSarm64SHA-25620c4a35fa244287766c1d1a19cd2e393b3fa451a96a81e5635401e69bef04b97
pg_exporter-1.0.2.linux-amd64.tar.gz Linuxamd64SHA-256d742111185f6a89fff34bfd304b851c8eb7a8e38444f0220786e11ed1934eff1
pg_exporter-1.0.2.linux-arm64.tar.gz Linuxarm64SHA-2560b1f4c97c1089c4767d92eb22419b8f29c9f46fb90ddfd1e8514cc42dc41054f
pg_exporter-1.0.2.linux-ppc64le.tar.gz LinuxSHA-256895083fd2c7fc5409cc1a2dbaaef1e47ac7aa6a3fd5db2359012922d90bcdcc3
pg_exporter-1.0.2.windows-amd64.tar.gz Windowsamd64SHA-2565f751228e7120604af9a482fb70197489fa633c38a0f2b6a3489393fbc6a10aa

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

Download asset
FileChecksum
pg_exporter-1.0.1-1.aarch64.rpm Linuxarm64MD5d5e2d6a656eef0ae1b29cd49695f9773
pg_exporter-1.0.1-1.x86_64.rpm Linuxamd64MD5cb01bb78d7b216a235363e9342803cb3
pg_exporter-v1.0.1.darwin-amd64.tar.gz macOSamd64MD567093a756b04845f69ad333b6d458e81
pg_exporter-v1.0.1.darwin-arm64.tar.gz macOSarm64MD52d3fdc10045d1cf494b9c1ee7f94f127
pg_exporter-v1.0.1.linux-amd64.tar.gz Linuxamd64MD5e242314461becfa99c3978ae72838ab0
pg_exporter-v1.0.1.linux-arm64.tar.gz Linuxarm64MD563de91da9ef711a53718bc60b89c82a6
pg-exporter_1.0.1_amd64.deb Linuxamd64MD5718f6afc004089f12c1ca6553f9b9ba5
pg-exporter_1.0.1_arm64.deb Linuxarm64MD557da7a8005cdf91ba8c1fb348e0d7367

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
Download asset
FileChecksum
pg_exporter-1.0.0-1.aarch64.rpm Linuxarm64MD533fe4dd8c5af56bef9b78fbf8f4fbbc9
pg_exporter-1.0.0-1.x86_64.rpm Linuxamd64MD5eba8426b2cf50a58db5353562727004a
pg_exporter-v1.0.0.darwin-amd64.tar.gz macOSamd64MD5f691282245f9ef7e712b88985ca0da11
pg_exporter-v1.0.0.darwin-arm64.tar.gz macOSarm64MD5c133c6077857edd500ab325bad4dc438
pg_exporter-v1.0.0.linux-amd64.tar.gz Linuxamd64MD53875487d26bcf9e9ec2e4dcb0c477ee0
pg_exporter-v1.0.0.linux-arm64.tar.gz Linuxarm64MD5395715fbee8894baf0e9c173f8e1babd
pg-exporter_1.0.0_amd64.deb Linuxamd64MD5f3b23e592f33587d0055984a6d9c2ef3
pg-exporter_1.0.0_arm64.deb Linuxarm64MD5a7305b9c46f8a0d476c9835cc8f01dfe

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_index
  • 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