Skip to content
Get started
Get started
Cron Jobs in Bun: Scheduled Background Tasks
guide · cron jobs

Work that runs on a clock.

Nightly reports, hourly cleanups, a health ping every thirty seconds. Schedules live in SQLite next to the jobs, so they survive a restart and need no extra scheduler process.

A scheduler is a named rule that keeps producing jobs on a queue. Create it once with upsertJobScheduler() and bunqueue fires the job on every tick, whether that tick comes from a cron pattern or a fixed interval. Scheduler IDs are global to one broker, not scoped by queue: use names such as reports:daily-report when several applications share a server.

Create a scheduler with upsertJobScheduler. It works in both embedded and TCP mode, in every SDK (Python: upsert_job_scheduler, Rust: upsert_job_scheduler, Go: UpsertJobScheduler, Elixir: upsert_scheduler), and calling it again with the same global ID replaces that scheduler definition instead of duplicating it. Reusing an ID with a different queue moves the definition to that queue.

import { Queue, Worker } from 'bunqueue/client';
const queue = new Queue('reports', { embedded: true });
// Every day at 9:00 AM
await queue.upsertJobScheduler('daily-report', {
pattern: '0 9 * * *',
}, {
name: 'daily-report',
data: { type: 'sales' },
});
// A normal worker processes the scheduled jobs
new Worker('reports', async (job) => {
console.log('Running report:', job.data.type);
}, { embedded: true });

Or from the CLI, against a running server:

Terminal window
bunqueue cron add daily-report -q reports -d '{"type":"daily"}' -s "0 9 * * *"
bunqueue cron list
bunqueue cron delete daily-report
Job Schedulers from the QueueNamed repeatable schedules on the Queue object
Cron RecipesFixed intervals, timezones, repeat-after-completion
Cron ReferenceExpression syntax, every scheduler option, MCP