Execution modes

What has to be true before a workflow can run, the execution_mode policy and its per-request override, the 30-second synchronous cap, and which entry point defaults to which mode.

Everything in Integration Studio runs on one durable execution engine. A workflow's steps are executed one at a time against the graph you saved, each step's result is recorded, and a step that fails is retried according to its own policy. There is no second engine and no separate in-process fast path: a synchronous run and an asynchronous run execute the same workflow the same way — the only difference is whether the caller waits for the result.

This page covers what has to be true before a run can start, and how the mode is decided.

A workflow only runs when its build is ready

Saving a workflow does not make it runnable. Each save bumps the workflow's revision and queues a build that compiles the graph into an executable bundle. The build state is one of:

Build statusMeaning
pendingThe save landed; the build has not started yet.
buildingThe bundle is being compiled.
readyThe bundle exists and the workflow can run.
failedThe build failed. Fix the workflow and save again to re-queue it.

A run is rejected while the build status is anything other than ready. That applies to every path into a run — a manual start, a schedule firing, an inbound webhook call, an event. Cockpit shows the build state on the workflow, and starting a run from the editor while a build is in flight holds the request and starts it once the bundle is ready rather than failing.

Build state does not currently refresh by itself in the workflows list — a workflow that has finished building keeps reading pending until you reload the page.

A trigger firing that was refused this way is not lost: it lands under Missed runs, where you can replay it from the payload captured when the trigger fired.

Execution mode is a workflow-level policy

Every workflow carries an execution_mode. It is a policy about who may decide whether a caller waits, not a choice of engine:

execution_modeEffect
async_onlyDefault. The run is started and the caller gets an acknowledgement immediately. Asking for a synchronous run is refused.
sync_onlyThe caller always waits for the result. Asking for an asynchronous run is refused.
caller_decidesEither is allowed; the caller may override per request.

Under caller_decides, the two entry points default differently, and this catches people out:

  • A webhook call defaults to synchronous — the caller waits for the result, because a caller that bothered to make an HTTP request usually wants the answer.
  • Creating a run directly defaults to asynchronous — start it and walk away.

If a request asks for a mode the policy forbids, the request is refused before any run record is created. Nothing is left half-started.

You set the execution mode when you create the workflow. When you test a workflow from the canvas, the modes offered are the ones its execution_mode allows — one if it is pinned, both if the caller may choose.

Synchronous runs are capped at 30 seconds

A synchronous run holds the caller until the workflow finishes, and exceeds-30-seconds is a gateway timeout. The run itself is not cancelled by that — it keeps going and lands in the run history with its real outcome — but the caller has already been answered with a 504, so it must not treat the timeout as "did not happen".

Two consequences worth designing around:

  • Anything that lists a directory, walks a large file, or waits on a batch job in an external system does not belong on a synchronous path. Put it on a schedule or on an asynchronous webhook.
  • If a caller retries after a timeout, the workflow runs twice. Make workflows that write data idempotent — key the write on something stable from the payload rather than on the fact of the run.

Choosing a mode

SituationMode
A file pipeline, an ERP sync, anything on a scheduleasync_only — nobody is waiting
A caller that needs the result of the work in its responsesync_only, and keep the workflow short
One workflow serving both a waiting caller and an unattended schedulecaller_decides, and remember the webhook default

If in doubt, leave it asynchronous. A caller can poll or be notified; a caller that has been sitting on an open connection for 29 seconds cannot be rescued.

Integration Studio is a Cockpit surface. Workflows, triggers, runs and credentials are managed in Cockpit, and there is no partner-facing Integration Studio API to drive them from your own code. Where you want automation over the platform's data itself, that is the revenexx API — see Reaching Revenue Cloud.

Where to go next

Was this page helpful?