Skip to content

Performance Testing

The test/pg_relay_performance_test.sql script measures how many events your configuration can process per second. It ships with the repository and is safe to run against any development or staging database.

For a quick, guided introduction to running it, see Running the Performance Test in the User Guide. This chapter covers the mechanics in more detail.

What the test does

The test creates a pool of channel sets (a mix of INSERT channels and SELECT channels) before the timed loops start, so there is no setup overhead sitting inside the measurement itself. In each loop, it sends a batch of events (100 × the loop number) and checks how many have been processed before the next loop begins. Once every loop has finished, it waits for the queue to drain completely and reports the final throughput.

Channel mix: roughly 25% of the channels run an INSERT action (writing to a small test table); the remaining 75% run a SELECT ... LIMIT 1 action (reading from a test table). This is meant to reflect a realistic mix of read-heavy and write-heavy workloads.

Pool sizing:

Number of loops Channel sets created
1–20 20
21–40 40
41–60 80
61+ 150 (capped at 3,000 tables)

Running the test

Prerequisites: a running Processor, and psql connected to your database as a superuser.

\i test/pg_relay_performance_test.sql

The script asks for confirmation, then asks how many loops to run (10–999). Suggested starting points:

Goal Loops Total events
Quick check 10 5,500
Reliable baseline 20 21,000
Stress test 50 127,500

Interpreting the output

Count 100, Remaining 0      ← 100 events sent; queue already drained
Count 200, Remaining 0
Count 300, Remaining 0
Count 400, Remaining 46     ← backlog starting to grow
Count 500, Remaining 312    ← Processor can't keep up at 500/s
...
The Processor is able to process between 300 and 400 notifications per second
Now waiting for Queue to drain...
...
Average Notifications processed per second: 350.000

Breakeven is the loop where Remaining first becomes non-zero. In the example above, that falls somewhere between the 300 and 400 loops, meaning this particular configuration can handle roughly 300–400 events per second.

Average throughput is measured over the drain period — the sustained rate after the initial burst has finished.

Effect of workers

Run the test twice — once with --workers 1 and once with --workers 2 or --workers 4 — to see the difference extra workers make:

pg_relay --verbose --workers 1  # first run
pg_relay --verbose --workers 4  # second run

Actions involving blocking operations (HTTP calls, slow queries, table locks) benefit the most from additional workers. Fast, simple SQL actions benefit less, because their bottleneck is usually the network round-trip time per process_one call, and that is bounded by how many worker connections you have running.

Cleanup

The test removes all its own channels, tables, and functions at the end of each run. pgrelay.log and pgrelay.queue will still contain test records afterwards — run a purge after a heavy test:

SELECT pgrelay.purge(p_hours := 1);
SELECT pgrelay.purge_queue(p_hours := 1);

Continue to Building from Source to compile the extension and Processor yourself.