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,  id:,  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#

orderQueue.enqueue(  { ... },  {    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.


apiIntegrationQueue.enqueue(  { ... },  {    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.


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 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.