Skip to content
Get started
Get started
Flow Producer: Parent and Child Jobs in Bun
View Markdown
guide · flow producer

Jobs that wait for each other.

Some work only makes sense in order: resize every image, then build the album; charge each line, then close the invoice. A flow declares that shape once and bunqueue holds the parent until its children are done.

A flow is a tree of jobs. Children are queued immediately, the parent stays blocked until every child has completed, and then runs with access to what they returned.

The most common shape: a parent job that waits for its children. Children run first, then the parent runs with access to their results:

import { FlowProducer, Worker } from 'bunqueue/client';
type ReportData = {
month?: string;
source?: 'sales' | 'costs';
};
const flow = new FlowProducer({ embedded: true });
const rowsBySource = { sales: [120, 80], costs: [50, 20] };
const worker = new Worker<ReportData>(
'reports',
async (job) => {
if (job.name === 'build-report') {
const values = await job.getChildrenValues<{ rows: number[] }>();
return { report: Object.values(values) };
}
if (!job.data.source) throw new Error('source is required');
return { rows: rowsBySource[job.data.source] };
},
{ embedded: true }
);
const node = await flow.add<ReportData>({
name: 'build-report',
queueName: 'reports',
data: { month: '2026-01' },
children: [
{ name: 'fetch-sales', queueName: 'reports', data: { source: 'sales' } },
{ name: 'fetch-costs', queueName: 'reports', data: { source: 'costs' } },
],
});
const result = await node.job.waitUntilFinished(null, 10_000);
console.log(result);
await worker.close();
await flow.close();

Flow creation is one broker-side transaction in the Bun package and all six current external SDKs: addBulk commits every tree or none, and workers cannot see a leaf before the full graph exists. Previously published SDK versions that compose PUSH and UpdateParent remain compatible with the server, but their already-sent requests cannot gain PUSHF all-or-nothing visibility.

The Bun producer validates the complete graph before sending it and the broker validates it again. With a SQLite dataPath, one immediate transaction commits the graph before it is published to workers, even when individual nodes omit durable: true. PostgreSQL likewise admits the complete graph, dependency edges, queue registry changes, and durable events in one database transaction before any broker can claim a leaf. Without either persistent backend, embedded mode is intentionally memory-only: creation is still atomically visible to workers, but a process crash cannot recover it.

  • A flow may contain at most 10,000 jobs, at most 10 MB of data per job and 64 MB across the batch. A root is depth 0; descendants may be at most 100 edges below it.
  • jobId is allowed, but cannot be empty or contain :. Reusing any existing or retained flow ID—including durable job/DLQ rows, completion or timeout tombstones, retained results, and IDs still referenced by a waiting parent—rejects the whole request in either persistent backend.
  • name inside user data is preserved independently from the job’s own name. Keys beginning with __ are reserved for engine-owned flow metadata.
  • repeat, deduplication, debounce, and opts.parent are rejected inside an atomic flow because their independent lifetime/ownership semantics cannot participate safely in the graph transaction.
  • opts.group is preserved for every node, including id, BullMQ Pro intra-group priority, and maxSize. Group options are validated with the rest of the graph; an invalid option or full group rejects every node before either SQLite or PostgreSQL publishes a partial flow.
  • The four child-failure policies are mutually exclusive.

Wire values are checked at runtime too: IDs must be strings, link fields must be string arrays, booleans must actually be booleans, and parent metadata must match both sides of every edge. These checks happen before any queue counter, heap, dependency index, or selected-backend row changes.

Flow PatternsChains, fan-in, trees, reading child results, options
Flow Failure HandlingWhat a parent does when a child dies for good
Flow Producer ReferenceEvery producer method, job helper and step field