Skip to content

Do You Need This Book?

pgrelay.schedule is a small companion utility: a PostgreSQL type that answers one question — "when should this next run?" — for recurring schedules like "weekdays at 04:30 and 17:00," "the 2nd Tuesday of the month," or "every third week on Monday and Wednesday."

Who needs this book

Anyone storing a recurring schedule in a table column — a scheduled report, a maintenance job, a notification cadence — for pg_relay itself or for an application that also uses pg_relay. If you only need one-off or interval-based scheduling (p_run_at, p_expire_at on pgrelay.notify()), you don't need this book — that's already covered by the Sending Events chapter of the User Guide.

What it is, and why it exists

pg_relay itself only ever answers "run this action when this event arrives." It has no concept of recurrence — and deliberately so, because recurrence logic (day-of-month clamping, nth-weekday-of-the-month arithmetic, every-N-weeks anchoring) is a different, self-contained problem with its own edge cases. Several pg_relay-related applications — a notifier, a scheduled maintenance job, your own code — kept needing that same piece of logic. Rather than have each one invent its own, pgrelay.schedule gives them one shared, thoroughly tested definition of "recurring schedule" to build on.

It is not part of the pg_relay extension. pg_relay's own SQL and the Processor binary never reference it — installing or skipping it changes nothing about how pg_relay itself behaves. It lives in the pgrelay schema because it's conceptually part of the pg_relay ecosystem, but — like other companion utilities in this repository — it ships and installs separately, after the extension, as an optional addition.

How it fits with pg_relay's queue

This is the one thing worth being precise about: pgrelay.schedule only ever computes when. It never enqueues anything, and it never calls pgrelay.notify() itself. If you want pg_relay's Processor to actually dispatch scheduled work, your own code is responsible for calling pgrelay.notify() once a schedule says it's due — typically right after advancing a "next run" watermark column. The Watermark Pattern chapter shows the complete, concrete pattern, including exactly where that call goes.

Your table (e.g. myapp.job)
    s            pgrelay.schedule   -- "when should this recur?"
    next_run_at  timestamptz        -- computed by pgrelay.next_run(s, ...)
        │  your own code checks: next_run_at <= now() ?
    pgrelay.notify('your_channel', ...)   -- THIS is what actually queues work
    pgrelay.queue → the Processor dispatches it, exactly like any other event

The five modes, at a glance

A schedule is one composite value with seven fields; which fields are populated tells you the mode — there's no separate "kind" flag to keep in sync.

Mode Fields Example
Every matching weekday dow weekdays at 04:30, 17:00
Nth weekday of the month dow + nth 2nd Tuesday
Every N weeks dow + week_interval (+ anchor) fortnightly on Tuesday
Days of the month dom 3rd, 5th, 22nd
Independent per-day times day_times Mon 05:00; Tue 17:30 and 20:00; Wed 12:00

You never build one of these by hand — a set of constructor functions (pgrelay.weekdays(), pgrelay.nth_dow(), pgrelay.fortnightly(), pgrelay.on_day_times(), and so on) build and validate a schedule for you. Every evaluation function also has a pgrelay.schedule[] array overload, for combining several schedules — including different modes — into one answer. See Installation to get started, or jump straight to the API Reference if you already know what you're building.


Continue to Installation.