Skip to content

Delayed jobs

Job supports immediate execution and one future execution per enqueue request. Use delayed jobs for reminders, retry handoffs, provider syncs, delayed cleanup, trial lifecycle work, and other task execution that should happen after the current request.

Terminal window
await jobs.enqueue("send-email", {
to: "user@example.com",
subject: "Welcome",
})

Use delaySeconds when the task should run after a relative delay:

Terminal window
await jobs.enqueue("send-reminder", {
userId: "user_123",
}, {
delaySeconds: 3600,
})

Use runAt when you already have the execution timestamp:

Terminal window
await jobs.enqueue("trial-ending-email", {
userId: "user_123",
}, {
runAt: "2026-06-01T09:00:00.000Z",
})

runAt accepts a Date or an ISO timestamp string.

delaySeconds and runAt control the first delivery. Retry delays are controlled by the task retry policy:

Terminal window
jobs.task("sync-provider", {
retry: {
attempts: 5,
backoff: "exponential",
initialDelaySeconds: 30,
maxDelaySeconds: 900,
},
}, async (payload) => {
await syncProvider(payload.accountId)
})

enqueue returns a run ID. Store it when your app needs to show status or cancel future work:

Terminal window
const run = await jobs.enqueue("send-reminder", {
userId: "user_123",
}, {
delaySeconds: 3600,
})
const latest = await jobs.runs.get(run.runId)
await jobs.runs.cancel(run.runId)

Replay creates a new run from a previous run payload:

Terminal window
await jobs.runs.replay("run_123", {
reason: "customer requested another reminder",
})