Pausing and Resuming¶
A profile can be put under a maintenance/blackout window — the mailbox, relay, or M365 tenant itself being temporarily unavailable, not a fault in pg_relay_notifier.
Pausing¶
-- pause one profile for its default window (now() + 7 days)
SELECT pgrelay_notifier.pause('mailer');
-- pause one profile until a specific time
SELECT pgrelay_notifier.pause('mailer', now() + interval '2 hours');
-- pause EVERY profile at once (p_profile_name NULL)
SELECT pgrelay_notifier.pause(NULL, now() + interval '30 minutes');
pause(p_profile_name, p_pause_until) — p_profile_name NULL means every profile, not just one. p_pause_until:
- Omitted — defaults to
now() + 7 days. - A timestamp already in the past — treated as "don't pause at all": the call ends the profile not paused (
paused_untilis set toNULL), even if it was paused a moment before. It never raises and never silently leaves a stale pause sitting there.
Resuming¶
-- resume immediately
SELECT pgrelay_notifier.resume('mailer');
-- or schedule exactly when sending resumes, instead of resuming right now
SELECT pgrelay_notifier.resume('mailer', now() + interval '1 hour');
-- resume EVERY profile at once
SELECT pgrelay_notifier.resume(NULL);
resume(p_profile_name, p_resume_at) — same NULL-means-every-profile rule. p_resume_at:
- Omitted — resumes immediately (
paused_untilcleared toNULL). - Given — stored verbatim as the new
paused_until. This is functionally the same column write aspause(p_pause_until := x);resume()is just the more intuitive name to reach for when the intent is "let sending resume starting at this time" rather than "start a fresh pause."
Where the check happens¶
At dispatch(), not compose(). A message can still be drafted during a pause — only the actual enqueue into pg_relay's queue is rejected:
SELECT pgrelay_notifier.send('mailer', ARRAY['x@example.com'], 'Hi', 'body');
-- ERROR: profile mailer is paused until 2026-08-29 10:00:00+10
Because the check sits at the one real chokepoint every send path goes through, send(), send_mail(), and the attachment-variant UTL_MAIL functions all inherit it automatically — nothing extra needed on their part.
This split matters in practice: a draft composed during a blackout can still be dispatched with an explicit p_run_at, or by relying on the profile's own delay_seconds default, timed to land once the window ends — pausing doesn't force anyone to wait around and retry by hand.
A different "pause" from pg_relay's own¶
Don't confuse this with pg_relay's own pgrelay.disable('channel_name') — that stops an entire pg_relay channel at the queue level, which several notifier profiles (or entirely unrelated SQL-event producers sharing that channel) might depend on. pause()/resume() here work on one profile (or every profile) at the pg_relay_notifier level and never touch the queue at all. Reach for pgrelay.disable() to stop a channel outright; reach for pause()/resume() when the reason is specific to one mail endpoint being temporarily unavailable.
What pausing does not do¶
A notification already dispatched (status pending, sitting in pg_relay's queue) is unaffected by a later pause() call — pg_relay_notifier doesn't reach into the queue to retroactively pull anything back out; that's pg_relay's own territory, not this extension's. As of pg_relay v1.2, pg_relay itself provides pgrelay.cancel(p_id bigint) for exactly that case — combined with delay_seconds, that gives a DBA a way to handle an already-queued notification too, if it's ever needed. See pg_relay's own documentation for how to use it.
Access¶
pause()/resume() are admin-only (grant_admin()) — pausing a profile, especially every profile at once, is an operational decision, not a sending privilege.