Skip to content
Get started
Get started
Namespaces, Auto-Batching and Store-and-Forward
View Markdown
guide · queue

Sharing a server, and leaving it.

Namespacing so several environments can share one broker, batching that makes concurrent adds an order of magnitude faster, and draining an edge queue into a central one.

prefixKey namespaces queue membership, crons, stats, pause state, DLQ, and rate limits on a shared broker. The client prefixes the broker queue key; Queue.name keeps reporting the logical name. Custom jobId values remain broker-wide, so include your tenant/environment in each custom ID when it must be isolated too.

// Same server, fully isolated namespaces
const devQueue = new Queue('emails', { prefixKey: 'dev:' });
const prodQueue = new Queue('emails', { prefixKey: 'prod:' });
await devQueue.add('send', { to: 'tester@example.com' });
await prodQueue.getJobCountsAsync(); // never sees dev jobs

A prefixKey option exists in both TypeScript packages and the Python SDK. In the other SDKs, prefix the queue name directly (e.g. new Queue('dev:emails')). Custom job IDs still need an explicit namespace.

A Worker must use the same prefixKey to consume the prefixed queue:

const devWorker = new Worker('emails', processor, { prefixKey: 'dev:' });

In the other SDKs, give the Worker the prefixed name (e.g. new Worker('dev:emails', processor)).

Common patterns: dev: / staging: / prod: on one server, tenant-${id}: per customer, per-service prefixes in a monorepo, test-${runId}: for parallel test isolation.

Notes:

  • Queue membership, worker locks, counts, pause/drain/obliterate, rate limits, and cron schedulers are scoped by the prefixed queue key (two prefixes can reuse the same schedulerId).
  • Custom jobId ownership is broker-wide: dev:order-123 and prod:order-123 are distinct; two queues using plain order-123 refer to the same live identity. A prefix is naming isolation, not an authorization boundary.
  • Backward compatible: without prefixKey, behavior is unchanged. Works in embedded and TCP modes.
  • The only user-visible side effect: Job.queueName inside processors shows the prefixed key (e.g. dev:emails).

In TCP mode, concurrent queue.add() calls are transparently combined into single bulk commands. It is enabled by default with no code changes: sequential await add() sends immediately, while concurrent adds (Promise.all) can share one round trip. Throughput depends on batch shape, durability, database size, and backend; use the current benchmark workloads instead of treating an older point measurement as a universal rate.

const queue = new Queue('tasks', {
autoBatch: {
enabled: true, // default
maxSize: 50, // flush when the buffer reaches this size (default: 50)
maxDelayMs: 5, // max wait before flushing (default: 5)
},
});

Auto-batching is available in both TypeScript packages (bunqueue/client and bunqueue-client); in the other SDKs, use addBulk to batch producer traffic into one round-trip.

Drain a source queue to a remote bunqueue server. The usual edge/IoT pattern uses an embedded SQLite queue as the offline buffer and a central server as the destination; the same API also supports a TCP source broker:

const forwarder = queue.forward({
to: { host: 'queue.example.com', port: 6789, tls: true, token: process.env.BQ_TOKEN },
queue: 'central-name', // optional remote queue name (default: same)
concurrency: 4, // parallel forwards (default: 4)
durable: true, // push remotely with durable: true (default: false)
});
forwarder.on('forwarded', ({ id, remoteId, name }) => {});
forwarder.on('error', (err) => {});
await forwarder.close();

Only the Bun-runtime bunqueue package provides the forward() drain loop. Its source may be embedded or TCP, but only an embedded source provides the in-process SQLite offline buffer. Direct network writes do not retain jobs locally while the central broker is unavailable.

If the remote is down, locally persisted jobs stay in the source queue (retry, then DLQ) while that process and volume survive. Use durable: true locally if SQLite’s 10ms hard-crash window is unacceptable. Full guide: IoT & Edge.

GuideWhat it covers
Queue APICreate a queue in embedded or TCP mode
Adding Jobsadd, addBulk, priorities, delays, durability
Deduplication and Idempotent Job AddsIdempotent adds, dedup keys, custom job ids
Querying JobsFetch jobs, states, counts and results
Queue Control and MaintenancePause, drain, obliterate, clean and repair
Progress, Job Logs and DependenciesProgress, per-job logs and dependencies
Queue Rate Limiting and Global ConcurrencyRate limits and global concurrency caps
Job Schedulers from the QueueNamed repeatable schedules from the queue
DLQ Operations from the Queue ObjectFailed-job operations from the Queue object
Workers, Stats and Metrics from the QueueRegistered workers, stats and metrics windows
JobOptions ReferenceEvery JobOptions field, with defaults