Every method, spelled out.
The producer surface, what a processor can ask about its children mid-run, and the full field list of a step so you can build graphs programmatically.
Reference
Section titled “Reference”FlowProducer methods
Section titled “FlowProducer methods”| Method | Description |
|---|---|
add(flow, opts?) | BullMQ v5: tree where children complete before the parent (atomic) |
addBulk(flows[]) | BullMQ v5: add multiple flow trees (atomic, all-or-nothing) |
getFlow({ id, queueName, depth?, maxChildren? }) | Retrieve a flow tree by root job ID |
addChain(steps[]) | Sequential execution: A → B → C |
addBulkThen(parallel[], final) | Parallel then converge: [A, B, C] → D |
addTree(root) | Hierarchical tree with nested children |
getParentResult(parentId) | Exact result of one completed parent, embedded or TCP |
getParentResults(parentIds[]) | Ordered results for completed parents, embedded or TCP |
close() / disconnect() | Close the connection pool |
waitUntilReady() | Wait until the FlowProducer is connected |
The table describes the Bun package. SDK availability: add and addChain exist in all six SDKs; getFlow in TypeScript, Python, PHP and Go; addBulk and addBulkThen in TypeScript and Python; addTree, getParentResult and getParentResults in the Bun package only.
FlowProducer extends Node.js EventEmitter (BullMQ v5 compatible). Its
closing property is null while live, then becomes the stable Promise returned
by the first close() or disconnect() call. Repeated shutdown calls return
that same Promise, including if teardown fails.
The result helpers stay synchronous in embedded mode for compatibility and
return Promises in TCP mode. Always await them in portable code. They preserve
0, false, an empty string, and persisted null; an ID with no stored result
is omitted from the map (or resolves to undefined for the single read).
The Bun snippets in this guide are exercised in
test/flow-docs-examples.test.ts, including the complete Quick Start, chain,
fan-in, parent-first tree, per-queue defaults, bounded traversal, and both
failure-value APIs.
Job methods inside a worker processor
Section titled “Job methods inside a worker processor”| Method | Description |
|---|---|
job.getChildrenValues() | Results of all completed children |
job.getFailedChildrenValues() | Errors from children that failed with continueParentOnFailure |
job.getIgnoredChildrenFailures() | Errors from children that failed with ignoreDependencyOnFailure |
job.removeChildDependency() | Atomically detach this job from its parent; promotes the parent if it was the last pending child |
job.removeUnprocessedChildren() | Cancel all waiting/delayed children; active and finished children are unaffected |
In the external SDKs, getChildrenValues is available on the job in TypeScript and Python and on Queue (taking the job id) in TypeScript, Python, PHP and Go; the other four methods live on Queue in TypeScript and Python.
Step shape
Section titled “Step shape”// addChain / addBulkThen / addTreeinterface FlowStep<T = unknown> { name: string; // Job name queueName: string; // Target queue data: T; // Job data opts?: JobOptions; // Optional job options children?: FlowStep[]; // Child steps (addTree)}
// flow.add / flow.addBulk (children run BEFORE the parent)interface FlowJob<T = unknown> { name: string; queueName: string; data?: T; opts?: JobOptions; children?: FlowJob[];}// addChain / addBulkTheninterface FlowStep<T = unknown> { name: string; queueName: string; data?: T; opts?: JobOptions;}
// flow.add / flow.addBulk (children run BEFORE the parent)interface FlowJob<T = unknown> { name: string; queueName: string; data?: T; opts?: JobOptions; children?: FlowJob<T>[];}# add_chain / add_bulk_then steps and add / add_bulk nodes are plain dicts:step = {"name": "...", "queueName": "...", "data": {}, "opts": {}}node = {"name": "...", "queueName": "...", "data": {}, "opts": {}, "children": []} # children run BEFORE the parent// addChain steps and add() nodes are plain arrays:$step = ['name' => '...', 'queueName' => '...', 'data' => [], 'opts' => []];$node = ['name' => '...', 'queueName' => '...', 'data' => [], 'opts' => [], 'children' => []]; // children run BEFORE the parent// AddChaintype ChainStep struct { Name string QueueName string Data map[string]any Opts JobOptions}
// Add (children run BEFORE the parent)type FlowJob struct { Name string QueueName string Data map[string]any Opts JobOptions Children []FlowJob}// add_chainpub struct ChainStep { pub name: String, pub queue_name: String, pub data: Value, pub options: JobOptions,}
// add (children run BEFORE the parent)pub struct FlowJob { pub name: String, pub queue_name: String, pub data: Value, pub options: JobOptions, pub children: Vec<FlowJob>,}# add_chain steps and add/2 nodes are plain maps (note the :queue key):step = %{name: "...", queue: "...", data: %{}, options: []}node = %{name: "...", queue: "...", data: %{}, options: [], children: []} # children run BEFORE the parentflow.add() returns a JobNode: { job, children? }, recursively.
Where to go next
Section titled “Where to go next”| Flow Producer | Your first parent/child graph, and what is guaranteed |
| Flow Patterns | Chains, fan-in, trees, reading child results, options |
| Flow Failure Handling | What a parent does when a child dies for good |