To ensure optimum performance in Workflows, follow best practices for building your flows.
The Workflows API endpoint allows an external client to invoke a flow over HTTP. This is a powerful feature because it expands flows beyond those started by the built-in connector library. However, these flows require attention to ensure they successfully complete. See Invoking an API endpoint flow.
The primary challenge with the use of the API endpoint is that the Workflows engine doesn't make latency guarantees. This means that although flows run fast most of the time, sometimes flow execution times can vary by 10X or more.
Because the API endpoint closes its connection to a client at 60 seconds, a flow fails if the operation takes any longer than that. Some HTTP clients that invoke an API endpoint flow could have an even lower timeout than the default API timeout. For example, Okta inline hooks have a default timeout of 3 seconds.
A best practice when working with API endpoint flows is to structure your flow to be processed asynchronously. This means the caller (HTTP client) shouldn't need to wait for a specific response.
This is especially important when integrating with Okta hooks. For instance, consider a flow that starts with the synchronous registration or import inline hook. Instead, you can restructure that flow with Okta events that use the asynchronous User Created and User Okta Profile Updated event cards. Moving to the asynchronous pattern is more advantageous for both systems. A common example is recording the registration and import of a new user in a third system. If there isn’t a critical need for it to be there instantaneously, the asynchronous pattern gives a better experience.
One way to manage the risk of a timeout is to close the HTTP connection as quickly as possible. One best practice is to add the API Connector Close card as the first card in the flow. This allows the Workflows engine to immediately release its HTTP connection to the caller (HTTP client). Then the Workflows engine asynchronously processes the rest of the flow. See Close.
Another best practice is to use the combination of Call Flow Async and Flow Control Return Raw cards. They allow you to start processing work asynchronously and have fine-grained control over the HTTP response. See Call Flow Async and Return Raw.
If a client requires a synchronous response, pay extra attention to flow architecture to make sure you aren't introducing unnecessary latency and timeout risk.
Avoid external network calls. Calls can take hundreds of milliseconds of latency, not including the time the external service takes to process data. External calls occur in connector cards and HTTP cards. If external network calls are necessary, create a helper flow and use the Call Flow Async card to remove the calls from the synchronous flow.
Once the response is ready, return it immediately. You can use the API Connector Close card to return a value while the rest of the flow continues processing.
The Workflows engine executes many smaller actions more efficiently than fewer large actions. Flows that use excessive memory may be throttled or stopped to protect system resources. These are important techniques to improve flow performance and avoid out-of-memory, throttling, execution delays, stuck executions, or other issues.
When you can build multiple asynchronous flows, the Workflows engine intelligently schedules the work to complete your flow as fast as possible. If you have a large amount of asynchronous work to do from your parent flow, the best practice is to use the Call Flow Async card. This card continues processing your parent flow while the engine concurrently executes the helper flow specified as the input.
If you have a large list of items and need to process each item in a list, the best practice is to use the For Each - Ignore Errors card. This card takes a list and runs a helper flow for each item in that list, with optional concurrency. While the card name implies that it ignores errors, that is only true from the parent flow perspective. You can handle errors in your helper flows. See For Each - Ignore Errors.
If you only need to process a subset of items in a list, the best practice is to filter them using the Filter card instead of stopping a helper flow early. See Filter.
While helper flows are preferable to doing all the processing in a single large flow, keep in mind that the creation and execution of helper flows is overhead. If you can avoid them for jobs that you don't need to process, then your flow runs more efficiently.
When operating on a list of items and using a For Each card, use the With the following values section to pass only the data that the helper flow needs. You can pull individual data items out of the list you're iterating over by using the interface to pick the individual item to pass. For example, if operating on a list of users, pass only the single user’s required fields into the helper flow instead of the entire user object.
Streaming actions take lists of results and automatically execute a helper flow for each item asynchronously. This process is optimized so the parent flow paginates through the data and creates the helper flows with low memory consumption.
Be mindful that non-streaming result set options lead to increased flow memory usage. Cards that feature the option Stream Matching Records in the Result Set field support streaming actions. The Find Users, List Users with Search, and List Users Assigned to Applications action cards for the Okta connector return lists and support streaming. See Set up the stream matching option with a helper flow.