Parallel & Race
Parallel node
The Parallel node runs multiple branches concurrently using Promise.all. All branches must complete before execution continues.
When to use
Use Parallel when you have independent work that does not depend on each other's results — for example, sending an email and a Slack notification at the same time, or fetching data from two separate APIs.
Adding a parallel node
- Drag a Parallel node onto the canvas.
- Connect the output of the node to the first step of each branch you want to run concurrently.
- Optionally connect a merge point after the parallel node to continue after all branches finish.
Generated code
await Promise.all([
step.do('Send Email', async () => {
await fetch('https://api.resend.com/emails', {
/* ... */
})
}),
step.do('Send Slack Message', async () => {
await fetch('https://slack.com/api/chat.postMessage', {
/* ... */
})
}),
step.do('Log to Analytics', async () => {
await fetch('https://api.segment.io/v1/track', {
/* ... */
})
}),
])INFO
Each branch inside a Parallel node runs in the same Cloudflare Workflow instance. They share the same durable execution guarantees — if the workflow is interrupted mid-parallel, only the incomplete branches re-run on resume.
Race node
The Race node runs multiple branches concurrently using Promise.race. The first branch to complete wins; all others are abandoned.
When to use
Use Race when you want to take the fastest result from multiple sources — for example, querying two AI providers and using whichever responds first.
Generated code
const result = await Promise.race([
step.do('Query Provider A', async () => {
const res = await fetch('https://api.provider-a.com/generate', {
/* ... */
})
return await res.json()
}),
step.do('Query Provider B', async () => {
const res = await fetch('https://api.provider-b.com/generate', {
/* ... */
})
return await res.json()
}),
])WARNING
Branches that lose a race are not automatically cancelled — Cloudflare Workflows does not support step cancellation. The losing branches complete their current step.do() call before the workflow moves on, but their results are discarded.
Accessing parallel results
When individual parallel branches need to return values, assign the Promise.all call to a variable:
const [emailResult, slackResult] = await Promise.all([
step.do('Send Email', async () => {
return { messageId: '...' }
}),
step.do('Post Slack', async () => {
return { ts: '...' }
}),
])In AwaitStep, downstream steps reference the parallel node's output, which contains the combined results array.