Best practices for building flows
To ensure optimum performance in Workflows, follow best practices for building your flows.
Effective use of the API endpoint
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 that they complete successfully. See Invoke an API endpoint flow.
API endpoint timeouts
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.
Structure flows asynchronously
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.
Place the API Connector Close Card first in a flow
One way to manage the risk of a timeout is to close the HTTP connection as quickly as possible. A 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.
Keep synchronous flows simple and fast
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.
Effective use of the Workflows engine
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.
Use helper flows to split large processing jobs
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, a 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, a 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, this is only true from the parent flow perspective. You can handle errors in your helper flows. See For Each - Ignore Errors.
Avoid complex error handling blocks
To avoid parsing errors caused by complex error handling, Okta recommends a limit of no more than three nested If Error blocks.
Filter large sets
If you only need to process a subset of items in a list, 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.
Avoid passing lists into helper flows
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.
Use streaming actions when possible
Streaming actions take lists of results and automatically execute a helper flow for each item asynchronously. This process is optimized so that 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 use. 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 Stream matching records with a helper flow.