Parallel Execution via pg_relay¶
The collection engine normally runs a suite's checks sequentially, in order, in your own session — simple, predictable, and fine for most deployments. But a large suite on a busy system is as slow as the sum of its checks. If the pg_relay extension (a queue-and-worker job dispatcher, also by Pebble IT) is installed, a suite can opt in to parallel execution: pghf.execute_check_run() then enqueues one pg_relay event per check instead of running it, and pg_relay's workers execute them concurrently — the degree of parallelism is simply however many workers your pg_relay deployment runs.
This is entirely opt-in, per suite. A suite that doesn't ask for it, or a server without pg_relay, behaves exactly as before.
Enabling it¶
Two steps. First, mark the suite:
Second — once per database, by an operator with pg_relay management rights — register the channel pg_relay will dispatch on:
SELECT pgrelay.register(
p_channel => 'pghf_check',
p_action => 'CALL pghf.execute_relay_check($1)',
p_notes => 'pg_health_framework parallel check execution',
p_action_type => 'sql',
p_concurrency_mode => 'channel_payload');
('channel_payload', available from pg_relay 1.1, lets different checks run in parallel while guaranteeing two events for the same check of the same run never run concurrently — extra insurance on top of the framework's own duplicate guard.)
What changes at run time¶
With both in place, pghf.execute_check_run() still walks the suite in order and still applies every gate it always has — a blackout window, version/topology qualification — logging those skips inline exactly as before (a check that was never going to run has nothing to parallelize). Every check that would have run inline is enqueued instead, and pghf.execute_relay_check() — the worker-side twin — performs the identical invoke/contract-check/error-capture/logging sequence for one check each, in parallel. The run's record notes what actually happened: run_via_pg_relay is true only if at least one check was genuinely enqueued.
Nothing breaks if pg_relay isn't ready. No pg_relay installed → a NOTICE, and the run proceeds sequentially. Channel unregistered, inactive, or not callable → one WARNING on the first failed submission, and that check plus every remaining one runs inline — the run always completes, degraded rather than broken.
A relay run finishes later, not when the CALL returns¶
This is the one behavioural difference to internalise: when execute_check_run() returns, it has finished submitting — workers are still executing. The run's finish time is stamped by whichever worker lands the final result (pghf.get_run_status()'s is_collection_complete tells you when). Two consequences the framework enforces for you:
pghf.evaluate_run()refuses a relay run that hasn't finished collecting. Evaluation may only ever happen once per run, so evaluating early would permanently lock the late-landing checks out of a verdict. Wait foris_collection_complete, then evaluate.pghf.run_and_evaluate()waits for you. It polls for completion (up top_relay_wait, default 5 minutes) before evaluating, and raises on timeout — leaving the run itself intact to evaluate manually once the workers catch up.
Suite order still controls submission order, but workers complete in whatever order they finish — under parallel execution, member position stops being an execution-order guarantee.
What the worker environment means for checks¶
Relay-dispatched checks run as pg_relay's worker role, not as whoever called execute_check_run(). That role needs the same access an operator needs — INSERT on pghf.raw_results, UPDATE and SELECT on pghf.runs, SELECT on pghf.raw_results/pghf.run_config, plus whatever the check bodies themselves read (pg_monitor membership covers the built-ins). A worker role with narrower rights than your usual operator can genuinely collect different results — for example, redacted activity queries without pg_monitor. See The Access Model.
Checks also run with search_path pinned to pg_catalog, public in the worker (pg_relay's own dispatcher would otherwise leave them an unusable path). Built-in checks only read system catalogs and don't care; a custom check that reads objects in any other schema should schema-qualify them — good practice regardless, and under relay it's required.
Full parameter details, including pghf.execute_relay_check() itself: the Reference Guide.
Continue to Alert Status.