- Docs
- Queue
- Job Options Reference
Every option, with its default.
The complete per-job option surface, what each field changes, and what you get when you leave it out.
Job Options Reference
Section titled “Job Options Reference”Pass options with each add. The field names follow the host language while the broker receives the same values:
await queue.add('report', data, { priority: 10, delay: 5000, attempts: 5, jobId: 'report-42', durable: true,});await queue.add('report', data, { priority: 10, delay: 5000, attempts: 5, jobId: 'report-42', durable: true,});queue.add( "report", data, priority=10, delay=5000, attempts=5, job_id="report-42", durable=True,)$queue->add('report', $data, [ 'priority' => 10, 'delay' => 5000, 'attempts' => 5, 'jobId' => 'report-42', 'durable' => true,]);queue.Add("report", data, bunqueue.JobOptions{ "priority": 10, "delay": 5000, "attempts": 5, "jobId": "report-42", "durable": true,})queue.add("report", data, JobOptions { priority: Some(10), delay: Some(5000), attempts: Some(5), job_id: Some("report-42".into()), durable: Some(true), ..Default::default()})?;{:ok, _job} = Bunqueue.Queue.add(queue, "report", data, priority: 10, delay: 5000, attempts: 5, jobId: "report-42", durable: true )Python uses snake_case keyword arguments and Rust uses snake_case struct
fields. Go uses a JobOptions map; PHP and Elixir use the camelCase protocol
names shown in the table.
| Option | Type | Default | Description |
|---|---|---|---|
priority | number | 0 | Higher = processed first |
delay | number | 0 | Delay in ms before processing; a negative delay makes the job ready at once |
attempts | number | 3 | Max total executions, first run included (3 = 1 run + 2 retries) |
backoff | number | { type, delay, maxDelay? } | 1000 | Backoff base in ms, or { type, delay, maxDelay? } ('fixed' is fixed; 'exponential' or any other type is exponential); maxDelay caps each retry delay (default: 1 hour, max: 1 day) |
timeout | number | - | Processing timeout in ms |
jobId | string | - | Custom ID for idempotent adds |
deduplication | object | - | TTL-based dedup (id, ttl, extend, replace) |
removeOnComplete | boolean | false | Auto-delete after completion |
removeOnFail | boolean | false | Auto-delete after failure |
stallTimeout | number | - | Per-job stall timeout override |
repeat | object | - | Repeating job config (every, pattern, limit, tz, immediately, startDate, endDate, …) |
durable | boolean | false | SQLite: bypass its write buffer; PostgreSQL is already transactional |
lifo | boolean | false | Process newest first |
group | { id, priority?, maxSize? } | - | Assign a fair job group, optional 0-first intra-group priority, and atomic pending-depth cap |
parent | { id, queue } | - | Parent job reference for flows |
stackTraceLimit | number | 10 | Max stacktrace lines stored per failure |
keepLogs | number | - | BullMQ-compat metadata: stored on the job, not applied automatically. Log trimming happens only when a clear-logs call passes its own keepLogs |
timestamp | number | now | Override the job’s creation timestamp (createdAt) |
failParentOnFailure | boolean | false | Flow: a terminal child failure fails the parent |
continueParentOnFailure | boolean | false | Flow: parent continues despite this child’s terminal failure |
ignoreDependencyOnFailure | boolean | false | Flow: parent ignores this failed child’s dependency |
removeDependencyOnFailure | boolean | false | Flow: remove this child from the parent’s dependencies on failure |
sizeLimit | number | - | BullMQ-compat metadata: stored on the job, not enforced by the broker |
debounce | { id, ttl } | - | Legacy BullMQ alias: stored on the job, not enforced — use deduplication |
Numeric options are validated before the job is admitted, with the same rules in
embedded and TCP mode. Only a value no job can run with is rejected: a value that is
not a number, NaN or an infinity, a negative timeout, ttl or backoff.delay, a
backoff.maxDelay above one day, and a
timestamp outside the JavaScript date range. A numeric string such as '3' is read
as its number. Everything else is accepted, as in 2.9.10:
prioritycan be any finite number (fractions and BullMQ’s2,097,152included);attemptsof0or less runs the job once, like1; a fraction rounds up;Infinityor a value above 2,147,483,647 retries up to 2,147,483,647 times;timeout,stallTimeout,backoff,delay,ttl,deduplication.ttl,debounce.ttlandrepeat.everyhave no practical upper limit (a duration above about 136,900 years is clamped to it);stackTraceLimit,keepLogsandsizeLimitare stored as given.
An invalid option makes add() throw, for example timeout must be at least 0;
addBulk() throws jobs[i]: ... and admits nothing. Messages name the option you
passed (attempts, deduplication.ttl, debounce.ttl).
A negative delay makes the job ready at once, in every mode and entry point, as in
2.9.10: its run time is in the past (now + delay), so among jobs of the same priority
it runs ahead of ready jobs added before it with a later run time. So
{ delay: runAt - Date.now() } is safe when runAt has already passed. The same holds
for the delay argument of changeDelay() (a PostgreSQL broker applies a negative one
as “now”, as in 2.9.10); a past moveToDelayed() timestamp means “now”. ttl cannot be negative.
At the same priority, LIFO jobs run newest-first ahead of FIFO jobs. Priority always remains authoritative, so a lower-priority LIFO job cannot overtake a higher-priority FIFO job.
The top-level priority rule above applies to ungrouped jobs. For grouped jobs,
put priority inside group: group.priority accepts integers from 0 through
2,097,151, where 0 is highest and positive values run in ascending order.
group.maxSize must be a positive safe integer. A full group rejects a single
add or an atomic flow admission. PostgreSQL bulk adds are transactional;
memory/SQLite bulk adds, embedded or over TCP, can retain the jobs accepted
before the one that exceeds the cap, then throw. See group admission semantics.
Processing timeout values are measured from the active transition and use an
absolute next-deadline timer. Concurrent jobs retain their individual deadlines.
The broker’s timeout transition is authoritative: a processor outcome that
arrives afterward is ignored for that exact lease generation, without emitting
a contradictory local Worker event. A later retry uses a new lease and is not
suppressed.
parent creates a real dependency edge to an existing pending job. The parent
moves to waiting-children, runs only after every linked child finishes, and
exposes child results through getChildrenValues(). This works across queues
and is committed atomically in both embedded and TCP modes, including
addBulk(). A missing, active, completed, or failed parent rejects the child;
the rejected child is not left in the selected memory, SQLite, or PostgreSQL
backend. Use FlowProducer when the parent and children must all be created as
one new graph.
Where to go next
Section titled “Where to go next”| Guide | What it covers |
|---|---|
| Queue API | Create a queue in embedded or TCP mode |
| Adding Jobs | add, addBulk, priorities, delays, durability |
| Deduplication and Idempotent Job Adds | Idempotent adds, dedup keys, custom job ids |
| Querying Jobs | Fetch jobs, states, counts and results |
| Queue Control and Maintenance | Pause, drain, obliterate, clean and repair |
| Progress, Job Logs and Dependencies | Progress, per-job logs and dependencies |
| Queue Rate Limiting and Global Concurrency | Rate limits and global concurrency caps |
| Job Schedulers from the Queue | Named repeatable schedules from the queue |
| DLQ Operations from the Queue Object | Failed-job operations from the Queue object |
| Workers, Stats and Metrics from the Queue | Registered workers, stats and metrics windows |
| Namespaces, Auto-Batching and Store-and-Forward | Namespaces, auto-batching, store-and-forward |