Notifications at a Glance¶
An optional layer sits on top of evaluation: register a notification — scoped to one check, one category, or globally — and the evaluation engine fires it automatically when a covered check's confirmed severity meets the set you choose. Entirely opt-in: with none registered, nothing behaves differently.
You make two orthogonal choices per notification.
When does it fire? — trigger_mode:
on_change— fire once when the severity crosses into your set (a'breach'), and — withfire_on_clear— once when it drops back out (a'clear'). This is the right shape for a persistent, polled condition: you're told when it goes bad and when it recovers, not on every poll in between.on_state— fire on every evaluation whose severity is in the set. This is the right shape for on-event checks, where each occurrence is a distinct real-world event that each deserves its own notification (500 occurrences → 500 notifications), and for "nag while it's still bad" reminders. An optional per-notificationcooldownthrottles it (engine-guaranteed, anti-flap — an interveningoknever resets it).
The severity set is either an explicit p_severities => ARRAY[...] or a p_min_severity floor (which expands to that rank and everything worse). Register several notifications on one check to fan out — and, with on_state, to route a different routine per severity result (ARRAY['critical'] → page, ARRAY['ok'] → "recovered").
How is it delivered? — delivery_kind. Every firing lands in the durable outbox pghf.notification_log first, then:
outbox— nothing more; a pull consumer drainspghf.list_pending_notifications()and acknowledges withpghf.mark_notification_delivered().notify— also a standard PostgreSQLNOTIFYof the outbox row's id on a channel, as a doorbell (plain core Postgres, nothing to do with pg_relay; a missedNOTIFYloses nothing — the row is still pending).pg_relay_notify— instead enqueues the outbox row's id via pg_relay'spgrelay.notify()for worker delivery. Requires the pg_relay extension — choosing it without pg_relay installed is rejected outright (a delivery kind that cannot run is an error, not a silent no-op).function— runs a routine you registered, inline, and the engine records'delivered'/'failed'.
-- polled: page the team when anything, anywhere, first reaches critical (and clears)
SELECT pghf.create_notification('crit pager', 'notify', p_min_severity => 'critical',
p_channel_name => 'pghf_alerts', p_fire_on_clear => true);
-- on-event: one notification per occurrence, delivered by your own function
SELECT pghf.create_notification('job failed', 'function', p_check_id => 'X01-003',
p_trigger_mode => 'on_state', p_severities => ARRAY['critical'],
p_routine => 'my_schema.alert(bigint, bigint, jsonb)'::regprocedure);
Because delivery is one durable outbox, wiring in your own notification system is one place to plug into, and pg_relay_notifier is simply one consumer of it — optional, never required. The outbox payload is self-contained (it includes the offending record_pk and source_table for on-event checks), so pghf.list_pending_notifications() or pghf.notification_context(evaluation_id) gives a consumer everything it needs with no joins, and pghf.list_notification_log() answers "did we notify, and was it delivered?" end to end.
The full guide — every parameter, the exact firing rule with worked examples, the manage-and-troubleshoot lifecycle, wiring your own delivery, and the optional pg_relay_notifier path — is its own book: Notifications.
Once per run, not per evaluation — run hooks. Notifications fire per evaluation. When you want the whole run instead — hand its results to an external system as one document, stamp an audit record, refresh a summary — register a run hook with pghf.register_run_hook(name, routine, run_sequence): a (uuid) RETURNS void routine the evaluation engine calls exactly once per evaluated run, inside the final evaluation's transaction, so its work commits or rolls back with the run. A raising hook is a warning, never a failed evaluation. Same trust tier as a notification routine; see the Reference Guide.
Continue to Retention and Cleanup.