A single TPS number is not evidence. It is meaningful only with the workload, client count, server configuration, hardware, timing, and raw output that produced it. pg-perf-bench sweeps controlled load and packages the result with that environment evidence.

The payoff

Release decisions can be based on a comparable saturation curve instead of an isolated “looks fast” run. When results differ, the report shows whether the database changed or the methodology and environment changed underneath it.

Real tasks it helps with

Pre-production capacity check

Sweep client concurrency on release-like hardware and verify where throughput peaks, latency rises, and CPU or storage saturates.

Configuration A/B

Recreate the benchmark database for each point, change one reviewed configuration candidate, and compare validated reports.

Hardware acceptance

Compare two hosts while retaining CPU, memory, storage, filesystem, PostgreSQL settings, and exact workload evidence.

Performance regression gate

Keep JSON artifacts for automation and a self-contained HTML report for release review and long-term evidence.

What happens in one sweep

Controlled iteration lifecycle
clients: 1 --------> 4 --------> 16 --------> 32
           for every measured point:
           drop + recreate dedicated database
                         |
                    initialize data
                         |
              run pgbench + sample host
                         |
               preserve raw output + facts

all points --> saturation curve --> maximum TPS + latency
     host + PostgreSQL + methodology evidence --> JSON / HTML

Operating modes

Mode Purpose Mutation
benchmark Run a client or duration sweep with a packaged or custom workload Drops and recreates only the explicitly confirmed benchmark database
collect-sys-info, collect-db-info, collect-all-info Capture host, database, or combined environment facts Read-only collection
join Validate comparability and combine existing reports Artifacts only
render/summarize Rebuild HTML or emit a compact deterministic summary Artifacts only
Transport local, existing docker container, or ssh target Depends on selected operation

Run a packaged workload

Use only a dedicated disposable database: the command recreates it before every measured point. Store the password in a libpq password file created outside shell history. Restrict that file to the current user with mode 0600.

# /run/secrets/pg-perf-bench.pgpass:
# 127.0.0.1:5432:*:postgres:<password>
chmod 0600 /run/secrets/pg-perf-bench.pgpass

PGPASSFILE=/run/secrets/pg-perf-bench.pgpass pg-perf-bench benchmark \
  --connection-type local \
  --allow-database-reset \
  --host 127.0.0.1 \
  --port 5432 \
  --user postgres \
  --database pg_perf_bench_test \
  --pg-data-path /var/lib/postgresql/18/main \
  --pg-bin-path /usr/lib/postgresql/18/bin \
  --workload-profile pagila \
  --workload-scale 1 \
  --pgbench-clients 1,4,16 \
  --report-name pre-go-live

Know the boundary

Benchmark mode is intentionally destructive to the selected database and refuses PostgreSQL maintenance databases. It is not a production traffic generator. Run it against an isolated target - ideally a pg-stand environment - and do not compare reports until their workload, server, client location, and methodology are demonstrably compatible.

GitHub repository ↗ PyPI package ↗