Loop iterations can run in parallel
Yes: Orchestrate can process a Loop step's iterations in parallel rather than one at a time. The only documented way to make them run in order is the Force Sequential Processing checkbox, and it sits on the Loop's Early Stop Condition, not on the Loop step itself.
Workday's docs do not say how many iterations run at once, and the Batch Loop and Join Loop reference pages say nothing about concurrency either way. Design every loop body as if iterations can overlap and finish in any order, unless you have forced the Loop to run sequentially.
How to force a Loop to run sequentially
- On the Loop step, open the related actions menu and choose Create Early Stop Condition.
- Give it a Reference Name.
- Enter an Early Stop Condition expression.
- Select Force Sequential Processing.
The checkbox stays inactive while the Early Stop Condition expression is the literal false. If you want sequential processing without stopping early, the condition still has to be an expression. One of Workday's App Catalog sample apps, a vehicle registration app with translations, does this with a condition that can never be true:
1.equals(0)
and Force Sequential Processing selected. The loop runs every item, one after another.
If the loop really should stop early, write the real condition instead. A loop with an Early Stop Condition outputs a boolean, did.Stop.Early, which is true when the condition ended the loop. Read it after the loop to tell "processed everything" from "stopped at the condition".
What sequential processing costs
Create Loop Early Stop Conditions carries a note that forcing sequential processing can significantly increase the orchestration's processing time and may cause a timeout that would not otherwise have happened. The limits that time runs into are on the runtime limits page:
| Context | Limit |
|---|---|
| ContextSynchronous orchestration triggered by a presentation page | Limit25 seconds |
| ContextSynchronous orchestration (Extend apps), Home Card orchestration | Limit5 minutes |
| ContextAsynchronous (Extend apps) and Integration System orchestrations | Limit48 hours |
| ContextIndividual process, app promoted to production | Limit60 minutes |
| ContextIndividual process, app not yet promoted to production | Limit45 minutes |
A loop of 2,000 HTTP calls that finishes comfortably in parallel can exceed a 45-minute process in a non-production tenant once it runs one call at a time. Orchestrate starts a new process, with a fresh 60 or 45 minute window, at checkpoint steps such as Send Workday RaaS Request, Trigger Integration, Trigger Business Process, Trigger PDF Generation and Send HTTP Request with polling, according to Concept: Orchestration Processes. A plain Send HTTP Request inside the loop does not reset that window.
So force sequential processing only for a reason you can name:
- Each iteration depends on the previous one. For example, each call needs a value the previous call returned, or a record must exist before the next one refers to it.
- The target system must receive records in order, such as postings that have to arrive by effective date.
- The target cannot accept concurrent calls at all, and retrying with backoff is not enough.
A loop that only needs its output file in a particular order does not need sequential processing. The next section covers that case.
Getting output in a stable order without serialising the slow work
Collect results with an aggregation, not with steps that write to a shared place on each iteration. Add Aggregations lists strategies such as JSON Fold, XML Fold, CSV Fold, Text Fold, String List, Sum and Count, which condense every iteration's output into one value after the loop. A running total belongs in a Sum or Custom Fold, not in a value you try to update inside the loop.
Workday's docs do not state whether an aggregation keeps the input order when iterations run in parallel, and a Loop's Sort By only orders items before they enter the loop. So when the output order matters, split the work into two loops:
- In the first loop, do the slow work (the HTTP calls, the lookups) in parallel, and write a sequence key into each result. Workday's sample apps read a Loop's
itemNumberfor this; the e-invoice sample adds it to each JSON record withaddNumberValue("invoice_id", data.Invoices.itemNumber). Aggregate the results with a JSON Fold. - In the second loop, iterate over that aggregated array with Sort By set to the sequence key, force sequential processing, and build the output with a CSV, XML or Text Fold. This loop only reshapes data already in memory, so running it one item at a time costs little.
If the input already has a natural key (employee ID, effective date, line number), sort on that and skip the generated number. Sort By compares text lexicographically and numbers numerically, so convert a numeric ID held as a string before you sort on it, or 10 sorts before 9.
Parallel loops and external API limits
Parallel iterations mean parallel requests to the target. When a target answers with "too many requests", handle it in the request's retry policy rather than by making the whole loop sequential. In the orchestration's HTTP Retries settings, add a set of conditions on Status Code (for example 429) and choose the Retry-After Header backoff, which waits for as long as the response header asks, up to the Max Interval you set. Maximum Total Retries is capped at 60. Policies apply to Send HTTP Request, Send WWS Pagination API Request and Send Workday API Request, through each step's Retry Settings.
One detail from the same page catches loops out: without a custom retry policy that defines a successful response range, an unsuccessful HTTP response doesn't make the orchestration fail. In a parallel loop of hundreds of calls, a few rejected requests can pass without any visible error. Define the success range, or check the status code inside the loop and aggregate the failures into their own output. For the rest of the outbound request setup, see calling external APIs from Orchestrate.
Parallelism inside a single step
Create Values has its own documented form of parallelism. When the key/value pairs in one Create Values step don't depend on each other, Orchestrate may create them in parallel; when one value refers to another in the same step, it has to create them in sequence. Workday recommends grouping independent values apart from dependent ones and puts the typical gain at up to 4X for 100 or more independent pairs, 1.5 to 2X for 50 to 99, and little or none below 50. It matters most inside a loop body, where the step runs once per item.
How to check what your loop actually did
The run's output shows whether the loop behaved, not the configuration. After a change:
- Add a Count output to the loop's aggregation and compare it with the number of source items.
- If you forced sequential processing to protect an order, log the sequence key from inside the loop with a Log step and read the entries in order, or read the aggregated output back.
- If the loop has a real early stop, log
did.Stop.Earlyafter it. - Read the target system back for a sample of records, including the first and last, rather than trusting a Success status. Without a success range in the retry policy, rejected HTTP calls do not fail the run. For reading a run's step statuses and errors, see the Orchestrate errors guide.
For splitting large inputs into groups before they reach the loop body, see the Batch Loop guide. For how loop volume relates to memory and paging, see Orchestrate looping and pagination limits.