Skip to main content


Depending on the framework, creating a queue works a bit different. Take a look at the sidebar to find a guide for your framework.


async enqueue(
payload: T,
options: {
id?: string;
override?: boolean;

runAt?: Date;
delay?: number | string;
repeat?: {
every?: number | string;
times?: number;
cron?: string | [schedule: string, timezone: string];
retry?: (number | string)[];

exclusive?: boolean;
): Promise<Job<T>>

Enqueues a new Job and returns it.

Schedule for a specified date

birthdayQueue.enqueue(, {
runAt: user.birthday,

Delay by a week

welcomeUserQueue.enqueue(, {
delay: "7d", // same as 7 * 24 * 60 * 60 * 1000

Repeated job

todoReminders.enqueue(, {
runAt: todo.scheduled_date,
repeat: {
every: "1d",
times: 3,

Runs three times: At scheduled_date, one day later and two days later.

CRON Schedule

Cron Jobs

This example is about regular Jobs, executed on a cron schedule. If you're looking for Cron Jobs, take a look at the more idiomatic CronJob.

billingQueue.enqueue(undefined, {
id: "billing", // makes sure job isn't duplicated
override: true, // if another job with that ID already exists, override it
repeat: {
cron: ["* * * * 1 *", "Europe/Berlin"],

If no timezone is specified, it defaults to Etc/UTC.

Order Queue

{ ... },
id: "1234", // if two jobs share the same `runAt`, they're ordered by ID.
exclusive: true, // make sure only one job is executed at once

You can also specify { exclusive: true } as the third argument to the Queue constructor.


{ ... },
retry: ["10sec", "5min", "1h"]

Retries a jobs three times, until it successd: After 10 seconds, 5 minutes and 1 hour.

You can also specify { retry: [ ... ] } as the third argument to the Queue constructor.

Currently, there's a hard limit of 10 retry attempts.


async enqueueMany(
jobs: { payload: T; options?: EnqueueJobOpts }[]
): Promise<Job<T>[]>

Works just like .enqueue, but creates multiple jobs at once.

Currently, there's a hard limit of 1000 jobs to be created at once.


*get(): AsyncIterator<Job<T>[]>

A generator function that can be used to iterate over pending jobs:

for await (const jobs of queue.get()) {
// do something


getById(id: string): Promise<Job<T> | null>

Returns a job's representation, if it exists.


invoke(id: string): Promise<Job<T> | null>

Gets a job and invokes it, if it exists. Returns the job's representation.


delete(id: string): Promise<Job<T> | null>

Gets a job and deletes it, if it exists. Returns the job's representation.


A representation of a pending job. Can be retrieved using Queue methods.


id: string;

The job's id. If not specified during .enqueue, it's a random UUID generated by Quirrel.


endpoint: string;

The HTTP endpoint the job will be executed against. Is always the same.


body: T;

The job's payload.


runAt: Date;

The date the job is scheduled for.


count: number;

The repetition of this execution. Starts at 1, increments with each repetition / retry.


cron?: string;
times?: number;
every?: number;
count: number;

Repetition options of the job. count starts at 1 and is incremented with every execution.


exclusive: boolean;

If a job is marked as exclusive, that means there won't be any other job (in the same queue) executed at the same time. If applied to all jobs in a queue, that effectively guarantees serial execution.


invoke(): Promise<boolean>

Invokes the job. Returns false if it's already been executed / deleted.


delete(): Promise<boolean>

Deletes the job. Returns false if it's already been deleted / executed.