Scheduled Jobs
Run a collection module function on a recurring schedule using a cron expression.
What this is
A collection module can run one of its functions on a schedule. You declare a job
with a name and a cron expression, and the platform calls the matching function each
time the schedule is due.
Use this for recurring work such as sweeps, polls, and reconciliations. You write the
function and add a cron line. There is no infrastructure to set up.
Declaring a job
Add a scheduledJobs array to your module config. Each entry has a name and a
cronExpression:
{
"scheduledJobs": [
{ "name": "sweepStalePayments", "cronExpression": "0 * * * *" },
{ "name": "dailyReconcile", "cronExpression": "0 6 * * *" }
]
}Rules:
- name is required and must be unique within the module. It is both the job
identifier and the name of the module function the platform calls on each run. - cronExpression is required and uses standard cron. It is always evaluated in
UTC.
The name must match a function in your module code. For the sweepStalePayments
job above, your module needs a sweepStalePayments function:
export const sweepStalePayments = async ({ organization, environment }) => {
// your recurring work here
};Each time the job is due, the platform calls this function. If there is no function
with a matching name, the job has nothing to run.
If your module declares no scheduled jobs, leave scheduledJobs out.
Cron rules
Your cron expression is checked when the module is published. Two checks apply:
- It must be a valid cron expression.
- A job may run at most once per hour. Any schedule whose runs are ever less
than 60 minutes apart is rejected.
So
0 * * * *(the top of every hour) is allowed, but0,30 * * * *(every 30
minutes) is rejected.
Times are in UTC, so plan around UTC when you pick an hour. For example, 0 6 * * *
runs at 06:00 UTC.
When a schedule changes
When you publish a change to a job's cron expression, the job runs one more time on
its old schedule, and then follows the new schedule from the next run onward.
Keep this in mind when you move a job to a new time.
Renaming or removing a job in your config removes the old job. A job only exists while
it is declared.
How a run works
On each due run, the platform:
- Calls the module function named by the job.
- Passes the organization and environment as arguments. Scheduled jobs are not tied
to a single policy, so no policy is passed. - Records the run and works out the next run time from your cron expression.
If the run fails, the platform does not advance the schedule. It retries the run, and
if it keeps failing the run is set aside for investigation rather than lost.
Your function must be safe to re-run
Scheduled jobs run at least once. A run can be delivered more than once, and a
failed run is retried, so the same due job can call your function more than once. The
platform does not remove these duplicates for you.
Write your function so re-running it is safe. Guard side effects, make writes
behave like upserts, and treat "already done" as success. If you do not, a retry can
double up work such as duplicate charges or duplicate records.
Environments
Scheduled jobs run per environment:
- In Sandbox, your module's draft version runs.
- In Production, your module's live version runs.
Scheduled jobs are an opt-in feature. If your jobs are not running, they may not be
enabled for your organization yet. Contact Root to have the feature turned on.
Updated about 11 hours ago