Skip to content

Minimum Report Intervals

Evaluation is deliberately granular: every run judges every check, and that run-by-run history is exactly what a DBA working a problem needs to watch. But telling the DBA is a different matter — being paged every hour that there are still 10 invalid indexes, while already working on them, is how alert fatigue turns real alerts into ignored ones. A minimum report interval separates the two concerns: evaluation continues completely untouched, and each evaluation instead carries an advisory reportable flag that says whether a reporting consumer should surface it. Every consumer is free to honour the flag or ignore it.

SELECT pghf.set_report_interval('PGHF06-003', 1440);   -- this check: at most one repeat per 24 hours

Where the interval lives

The value is minutes, defined against the check only — exactly like a threshold: one value per check, applying wherever the check runs (suites decide what runs together; checks own what the results mean — and the severity the interval suppresses repeats of is itself computed per check, so the interval must be too). 0 means always report; NULL means no suppression at all. get_report_interval() reads it back. Like thresholds, this is your deployment's tuning, not part of what the check is: it works directly on built-in checks, and — like thresholds, and unlike this column's earliest behavior — is reset on every catalog reseed.

Seeded defaults

Every built-in check ships with a starting interval, derived from which seeded cadence suite it belongs to — a check that's evaluated every minute shouldn't repeat the same warning every single minute:

Suite Seeded interval
seeded-1m 15 minutes
seeded-5m 30 minutes
seeded-15m 60 minutes
seeded-1h 240 minutes (4 hours)
seeded-daily / seeded-weekly / seeded-on-demand NULL — no suppression

The three slower cadences are left unsuppressed deliberately: a check that only runs once a day (or once a week, or on demand) already produces a low-noise stream on its own, so layering a suppression interval on top would risk hiding a persistent problem behind an interval longer than the check's own run gap. pghf.set_report_interval() remains the one supported way to override any of this — your override survives until the next reseed, exactly like an edited threshold value.

This table is a recommendation, not something this framework enforces. These minute counts are calibrated to the cadence a check's assigned seeded suite is named for — there's no scheduler here (see Scheduling Health Checks), so nothing actually makes seeded-1m run once a minute; that depends entirely on whatever cron/orchestrator you point at it, if any. Run a built-in check from a suite of your own on a different schedule, purely by hand with no schedule at all, or skip these seeded suites and defaults entirely and rely on this project only for collection and evaluation against checks of your own — all fully supported. If your actual usage doesn't match a check's assigned cadence, the seeded interval is just a starting point you're expected to retune with pghf.set_report_interval().

The rule

Stamped per evaluation by the evaluation engine, over the check's one evaluation stream:

  1. Any change in confirmed severity is reportable immediately — in both directions. An info reported five minutes ago that escalates to warning is reported at once; so is a critical easing to warning, because "it's less bad now" is also something the DBA needs to know. Suppression never sits on a change.
  2. The same severity repeating is reportable only once the last reportable evaluation is older than the interval. A persistent problem re-surfaces once per interval — the daily nudge — instead of once per run, while the full evaluation history underneath stays intact and queryable.
  3. skipped never reports and never confuses the comparison. A check that self-skipped, or was suppressed by a blackout window, is transparent: "critical → (blackout) → still critical" is a repeat, not news.

Because the rule reads the same post-debounce confirmed severity as everything else, it composes with debounce and hysteresis automatically, and the special severities (invalid, error_in_performing_check) flow through it like any other value.

How consumers see it

pghf.get_results_sql() gains a reportable column, pghf.get_results_json() a reportable key, and both take p_reportable_only => true to pre-filter — so a notification pipeline that wants suppression honoured needs exactly one argument, and one that wants everything changes nothing:

SELECT * FROM pghf.get_results_sql('<run_id>', 'warning', p_reportable_only => true);

The event layer ignores the flag entirely — its transition-only firing is already its own, stricter suppression policy (it never repeats at all while a breach persists). The interval exists for the consumers that read full run results.

Full parameter details: the Reference Guide.

Continue to Parallel Execution via pg_relay.