How Scripting Works
Fluxify compiles the workflow DAG into one native JavaScript route handler. JavaScript from script blocks and js: expressions is emitted into that handler and runs directly in Bun's JavaScript runtime. There is no separate VM or graph traversal on the request path.
The Execution Flow
When you save a workflow, the compiler prepares its script code in four steps:
- DAG compilation: The compiler walks the workflow from its entrypoint and emits a native JavaScript function for the route.
- Script integration: Script blocks and
js:expressions are transformed into the generated function with their request context and workflow state available at runtime. - Import analysis: The AST parser finds static
importdeclarations, hoists them from request-time code, and resolves them once during compilation. - Direct execution: Workers receive the compiled handler and execute it directly in Bun for every matching request. Async code uses normal JavaScript
awaitsemantics.
Scripts Always Run Async
Every script is wrapped in an async function before it is compiled. That means you never have to opt in to await: use it anywhere, in any script block or js: field, and the engine waits for the result before it moves to the next block.
Plain computation
A script with no await simply runs to the end and returns.
const users = input.users || [];
const activeUsers = users.filter((u) => u.active);
return activeUsers.length;Waiting on something
Use await for calls that take time, such as an external API.
const userId = getQueryParam("userId");
const response = await httpClient.get(`https://api.example.com/users/${userId}`);
return response.data;Returning a promise works too: the engine waits for it.
Runtime Limits and Timeouts
There is no separate time limit for a single script. The whole run has one:
- Routes: the route's timeout setting (30 seconds by default), enforced by the experimental worker watchdog when
experimental.workerTimeouts.enabledis on. - Workflows: the workflow's own timeout setting (300 seconds by default).
Keep computations bounded, because an infinite loop blocks the route handler. Give outgoing calls their own timeout, and wrap risky code in try and catch, or add an Error Handler block. See Execution Limits & Safety.
Not sure which names your code can use in a given place? See Where Your Code Runs.
