Parallel Execution
Parallel execution lets you run independent steps concurrently inside a flow.
This is useful when multiple operations do not depend on each other and you want to reduce overall execution time without splitting the workflow into separate flows.
When to use parallel steps
Parallel execution is a good fit for work like:
- sending independent notifications
- writing an audit log while also publishing an event
- fetching unrelated data from multiple sources
It is not a good fit when one step depends on data produced by another step in the same group.
Defining a parallel block
flow
.parallel("fetch-data", [
{
name: "fetch-user",
fn: async (ctx) => { /* ... */ }
},
{
name: "fetch-posts",
fn: async (ctx) => { /* ... */ }
}
])
.step("process-all", (ctx) => {
// Runs after the whole parallel block finishes
});The next step after the block only starts once every step in the group has finished.
How it works
Inside a parallel block:
- all step functions are started
- each step still gets its own retries, timeout handling, and result object
- the flow waits until the entire group settles
- the group outcome is evaluated according to
failFast
Default failure behavior
By default, a parallel block does not fail the flow just because one step failed.
Instead, the block only fails the flow when all steps in that parallel group fail.
This means a mixed result like:
fetch-user: completedfetch-posts: failed
can still allow the flow to continue if failFast is not enabled.
This behavior is important and should be chosen intentionally.
failFast: true
If you want any failed step to fail the whole group, use:
flow.parallel("fetch-data", [
{ name: "fetch-user", fn: async () => {} },
{ name: "fetch-posts", fn: async () => {} }
], {
failFast: true
});With failFast: true, a single failed step is enough to make the group fail.
How to choose the right mode
Use the default mode when:
- partial success is acceptable
- the downstream flow can continue with missing or degraded data
- the group contains optional work
Use failFast: true when:
- all operations in the group are required
- partial success would leave the workflow in an invalid business state
- you want strict all-or-nothing behavior for that group
Parallel steps and compensation
Parallel steps can also define compensation.
If the group fails and some parallel steps already completed successfully, those completed steps may be compensated as part of the failure path.
That means the same rollback discipline used for sequential steps should also be applied inside parallel groups.
Best Practices
- Use parallel blocks only for independent work.
- Be explicit about whether partial success is acceptable.
- Add compensation to side-effecting parallel steps.
- Keep group size reasonable to avoid creating bursts against downstream systems.