# JobOptions Reference

Every bunqueue JobOptions field with its type and default: priority, delay, attempts, backoff, timeout, jobId, removeOnComplete, durable and the rest.

Canonical: https://bunqueue.dev/guide/queue/options/

---

import { Tabs, TabItem } from '@astrojs/starlight/components';

<div class="bq-wrap bq-hero">
  <span class="bq-eyebrow">guide · queue</span>
  <h1 class="bq-hero-h1 bq-bench-h1">Every option, <em>with its default.</em></h1>
  <p class="bq-hero-sub">The complete per-job option surface, what each field changes, and what you get when you leave it out.</p>
</div>

## Job Options Reference

Pass options with each add. The field names follow the host language while the
broker receives the same values:

<Tabs syncKey="lang">
<TabItem label="Bun">

```typescript
await queue.add('report', data, {
  priority: 10,
  delay: 5000,
  attempts: 5,
  jobId: 'report-42',
  durable: true,
});
```

</TabItem>
<TabItem label="Node.js / Deno">

```typescript
await queue.add('report', data, {
  priority: 10,
  delay: 5000,
  attempts: 5,
  jobId: 'report-42',
  durable: true,
});
```

</TabItem>
<TabItem label="Python">

```python
queue.add(
    "report", data,
    priority=10,
    delay=5000,
    attempts=5,
    job_id="report-42",
    durable=True,
)
```

</TabItem>
<TabItem label="PHP">

```php
$queue->add('report', $data, [
    'priority' => 10,
    'delay' => 5000,
    'attempts' => 5,
    'jobId' => 'report-42',
    'durable' => true,
]);
```

</TabItem>
<TabItem label="Go">

```go
queue.Add("report", data, bunqueue.JobOptions{
    "priority": 10,
    "delay": 5000,
    "attempts": 5,
    "jobId": "report-42",
    "durable": true,
})
```

</TabItem>
<TabItem label="Rust">

```rust
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()
})?;
```

</TabItem>
<TabItem label="Elixir">

```elixir
{:ok, _job} =
  Bunqueue.Queue.add(queue, "report", data,
    priority: 10,
    delay: 5000,
    attempts: 5,
    jobId: "report-42",
    durable: true
  )
```

</TabItem>
</Tabs>

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                                        |
| `attempts`         | `number`                    | `3`     | Max total executions, first run included (`3` = 1 run + 2 retries)   |
| `backoff`          | `number \| { type, delay }` | `1000`  | Backoff base in ms, or `{ type: 'fixed' \| 'exponential', delay }`   |
| `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`)                   |
| `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](/guide/queue/job-groups/), optional 0-first intra-group priority, and atomic pending-depth cap |
| `parent`           | `{ id, queue }`             | -       | Parent job reference for [flows](/guide/flow/)                       |
| `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` |

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;
embedded memory/SQLite bulk adds can retain the jobs accepted before the one
that exceeds the cap, then throw. See [group admission semantics](/guide/queue/job-groups/#add-grouped-jobs).

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.

:::tip[Related Guides]

- [Worker API](/guide/worker/), process jobs from queues
- [Dead Letter Queue](/guide/dlq/), handle failed jobs
- [Rate Limiting](/guide/rate-limiting/), control processing rates
- [Job Groups](/guide/queue/job-groups/), per-tenant FIFO and backpressure
- [Queue Group](/guide/queue-group/), manage multiple queues
  :::

## Where to go next

| Guide | What it covers |
| ------------------------------------------------------------------------- | --------------------------------------------- |
| [Queue API](/guide/queue/)                                                | Create a queue in embedded or TCP mode        |
| [Adding Jobs](/guide/queue/adding-jobs/)                                  | add, addBulk, priorities, delays, durability  |
| [Deduplication and Idempotent Job Adds](/guide/queue/deduplication/)      | Idempotent adds, dedup keys, custom job ids   |
| [Querying Jobs](/guide/queue/querying/)                                   | Fetch jobs, states, counts and results        |
| [Queue Control and Maintenance](/guide/queue/control/)                    | Pause, drain, obliterate, clean and repair    |
| [Progress, Job Logs and Dependencies](/guide/queue/progress/)             | Progress, per-job logs and dependencies       |
| [Queue Rate Limiting and Global Concurrency](/guide/queue/limits/)        | Rate limits and global concurrency caps       |
| [Job Schedulers from the Queue](/guide/queue/schedulers/)                 | Named repeatable schedules from the queue     |
| [DLQ Operations from the Queue Object](/guide/queue/dlq/)                 | Failed-job operations from the Queue object   |
| [Workers, Stats and Metrics from the Queue](/guide/queue/metrics/)        | Registered workers, stats and metrics windows |
| [Namespaces, Auto-Batching and Store-and-Forward](/guide/queue/advanced/) | Namespaces, auto-batching, store-and-forward  |