Schedulers & repeatables
Job Schedulers are the forward-looking way to run recurring work. NextMQ owns the scheduling clock, so repeating jobs fire even while your functions are cold.
Upserting a scheduler#
upsertJobScheduler creates or updates a scheduler by key. Use a cron pattern or a fixed every interval. Upsert is idempotent, so it is safe to run from startup code.
import { Queue } from '@nextmq/sdk'
const reportQueue = new Queue('reports')
// Cron: every day at 09:00 in a fixed timezone.
await reportQueue.upsertJobScheduler('daily-report', {
pattern: '0 9 * * *',
tz: 'Europe/Berlin',
}, {
name: 'report',
data: { kind: 'daily' },
})
// Fixed interval: every 15 minutes.
await reportQueue.upsertJobScheduler('healthcheck', {
every: 15 * 60 * 1000,
})Repeat options#
Common cron patterns:
| Pattern | Runs |
|---|---|
0 * * * * | At the top of every hour. |
0 9 * * * | Every day at 09:00 in the scheduler timezone. |
0 9 * * 1 | Every Monday at 09:00. |
| Option | Description |
|---|---|
pattern | Cron expression for the schedule. |
every | Fixed interval in milliseconds (alternative to pattern). |
limit | Maximum number of times to repeat. |
tz | Timezone for cron evaluation. |
startDate | Don't fire before this time. |
endDate | Don't fire after this time. |
immediately | Produce the first job right away rather than waiting a full interval. |
tz for calendar schedules that must follow a specific timezone. Cron schedules with tz follow that timezone's civil calendar, including DST. Fixed every schedules are duration-based.name, data, and safe job options. Template options cannot include jobId, repeat, delay, deduplication, or callbackUrl; scheduled jobs use the queue's canonical worker registration URL.What the worker receives#
A scheduler creates ordinary jobs. The worker sees the template name anddata, exactly as if you had called queue.add().
await reportQueue.upsertJobScheduler(
'daily-report',
{ pattern: '0 9 * * *', tz: 'Europe/Berlin' },
{ name: 'build-report', data: { range: 'yesterday' } },
)
new Worker('reports', async (job) => {
// job.name === 'build-report'
// job.data.range === 'yesterday'
})Reading and removing schedulers#
// All schedulers on the queue
const all = await reportQueue.getJobSchedulers()
// A single scheduler by key
const one = await reportQueue.getJobScheduler('daily-report')
// Remove a scheduler
await reportQueue.removeJobScheduler('daily-report')getRepeatableJobs, removeRepeatableByKey) is intentionally omitted — two ways to manage the same thing is worse than one. A limited repeat option on add() still exists for simple cases, but schedulers are preferred.Why this works when functions sleep#
The scheduler clock lives on NextMQ, not in your app. When a scheduled job is due, NextMQ produces it and calls your worker route via webhook — the same path as any other job. Your app doesn't need to be awake for the schedule to advance.
Create important schedulers in startup registration so a fresh deployment has both worker registration and repeat jobs in place. The full scheduler method and option list is in the SDK reference.
limit is reached or afterendDate. Remove or upsert the scheduler again when you intentionally want to resume it.