Skip to content

Node.js Runtime and SDK Libraries ​

Cloud Flow custom code runs in a controlled, server-side Node.js execution environment. It can use ioLoop's Server API, configured Connections, selected Node.js modules, and a curated set of third-party SDK libraries.

This is a key difference from Page Flow: Page Flow code executes in the visitor's browser, while Cloud Flow executes on the backend. Use Cloud Flow for processing that needs server-side capabilities, protected service credentials, or trusted application rules.

This guide explains the runtime model, how to use JavaScript and SDK libraries, and how to choose among Cloud Flow blocks, Server APIs, Connections, and direct SDK calls. For exact API signatures and block behavior, use the Backend Programming Guide.

Understanding the Runtime ​

Cloud Flow logic is built from visual programming blocks and custom JavaScript. ioLoop generates backend JavaScript from the Cloud Flow and executes it within a managed Node.js runtime.

The environment provides:

CapabilityPurpose
Cloud Flow blocksBuild server-side workflows visually, including Database, files, Web Hooks, Connections, and result handling.
Custom CodeRun JavaScript statements within a Cloud Flow.
Code ExpressionSupply a computed JavaScript value to another block.
ioLoop Server API ($io)Access supported Project-aware backend operations.
ConnectionsUse centrally configured service credentials and connection settings.
Curated Node.js librariesUse allowed Node.js core modules and supported third-party packages through require(...).
Flow ShareShare runtime values and functions between supported backend modules.
Cloud Flow logsInspect server-side diagnostics during testing and execution.

The runtime is not an unrestricted Node.js server. Project code does not install arbitrary npm packages or assume access to every built-in Node.js module, operating-system resource, or Node.js facility. Use the ioLoop Server API and the specifically available libraries for supported operations.

Likewise, server-side code should not depend on browser-only objects such as window, document, or the DOM.

Cloud Flow Blocks and JavaScript ​

Most Cloud Flow logic can be implemented with blocks, JavaScript, or a combination.

ApproachUse It For
Visual blocksClear workflow steps, standard Database and file operations, Connection calls, Web Hook responses, conditions, and result handling.
Custom Code blockFocused JavaScript statements, data transformations, SDK calls, and operations that are easier to express in code.
Code Expression blockA single expression whose result is passed to another block.
Blockly functionsReusable logic defined within a Cloud Flow module.
Flow ShareHelpers or values needed by more than one backend module at runtime.

A Custom Code block accepts JavaScript statements. A Code Expression must evaluate to one expression, not a multi-statement program. Keep expressions concise and use Custom Code when the logic becomes substantial.

For example, a Code Expression could calculate a value:

js
Number(quantity) * Number(unitPrice)

A Custom Code block could prepare a structured request:

js
const requestDetails = {
  eventId: selectedEventId,
  attendeeCount: Number(attendeeCount),
  requestedAt: new Date().toISOString()
};

These examples illustrate JavaScript syntax. The input variables must be intentionally available in the current Cloud Flow; declaring a local variable in one Custom Code block does not automatically expose it to other blocks.

Custom Code is generated into the flow inside its own scope. Use appropriate Blockly variables or functions for same-flow reuse, or Flow Share for supported runtime sharing. Do not rely on incidental names in generated JavaScript.

For editing, block scope, and save-time validation, see Cloud Flow Editor and Cloud Flow Custom Code.

Choosing the Right Backend Tool ​

Choose the simplest interface that provides the needed capability.

RequirementRecommended Starting Point
Standard Database, file, Web Hook, or Connection operationCloud Flow block
Precise Project-aware behavior in JavaScriptioLoop $io Server API
Common supported service operationConnection block or integration-specific Server API
Advanced provider functionalityConnection-backed SDK object or supported SDK library
Data that must persist between executionsProject Database or supported file storage
Runtime-only helper shared between modulesFlow Share
Repeated processing controlled by backend logicBackground Task with its own logic, such as an ioLoop timer

These approaches are complementary. Cloud Flow blocks provide convenient interfaces to backend functionality, while custom server-side code can call the supported Server APIs directly and use curated SDKs where appropriate.

The Server API is not identical to the Client API. It includes additional methods and broader backend capabilities, including Database functionality not available through browser-side $io.db.

Using the ioLoop Server API ​

The server-side $io object provides Project-aware backend functions. Depending on the task, Cloud Flow code can use supported APIs for:

  • Database operations and named queries.
  • Project files and file processing.
  • Web Hook requests, responses, and streaming.
  • Connection operations and SDK access.
  • Runtime timers, logging, and Flow Share.
  • Supported AI Agent functionality.

For example, $io.system includes functions for Connection calls, runtime logging, timers, and authenticated SDK objects.

Use the Server API reference for authoritative function signatures, parameter requirements, outputs, and error behavior. Do not assume an API call follows ordinary npm-library conventions or has the same signature as a corresponding Client API call.

Using Configured Connections ​

Connections manage external service authentication and configuration for the Project. Cloud Flow can then use the configured service without hardcoding its credentials in JavaScript.

A common workflow is:

  1. Configure the appropriate service under Integrations.
  2. Give the Connection a meaningful name.
  3. Choose a Cloud Flow block or Server API that supports the intended operation.
  4. Reference the configured Connection using the expected name and service.
  5. Handle both success and failure responses.
  6. Test the operation with the intended provider environment before publishing.

For standard operations, prefer a Connection block or supported integration-specific $io method. For more advanced provider features, use a supported authenticated SDK object.

For configuration and service-level guidance, see Using Connections and Connections.

Getting an Authenticated SDK Object ​

The Server API provides:

js
$io.system.sdkLibraryObjectFromConnection(serviceName, connectionName)

This function retrieves a supported SDK or service object using an existing Project Connection. It lets Cloud Flow call supported provider SDK functionality without placing the Connection's secrets directly in the code.

Stripe example ​

js
const stripe = $io.system.sdkLibraryObjectFromConnection(
  'stripe',
  'my-stripe-connection'
);

The resulting object can be used with supported Stripe SDK methods according to the SDK version provided by the ioLoop runtime and the permissions of the selected Connection.

Google Drive example ​

js
const drive = $io.system.sdkLibraryObjectFromConnection(
  'google.drive',
  'my-google-connection'
);

This provides a Google Drive client configured with authentication from the named Connection.

Google OAuth2 example ​

When an authenticated OAuth2 client is needed for a supported Google API:

js
const { google } = require('googleapis');

const auth = $io.system.sdkLibraryObjectFromConnection(
  'google.auth.OAuth2',
  'my-google-connection'
);

const gmail = google.gmail({ version: 'v1', auth });

The example illustrates combining an allowed Node.js package with a Connection-backed authentication object. Specific Google operations and scopes depend on the Connection's configuration and authorization.

Supported SDK service names ​

The supported service names for sdkLibraryObjectFromConnection are:

Service nameSDK object
openaiAuthenticated OpenAI SDK client
stripeAuthenticated Stripe SDK object
sendgridSendGrid mail client
twilioAuthenticated Twilio client
google.auth.OAuth2Authenticated Google OAuth2 client
google.driveGoogle Drive service client
google.sheetsGoogle Sheets service client
google.docsGoogle Docs service client
google.calendarGoogle Calendar service client
google.oauth2Google OAuth2 service client
squareAuthenticated Square SDK client
hubspotAuthenticated HubSpot SDK client

Package names used with require(...) and service names accepted by sdkLibraryObjectFromConnection are separate lists. A curated package does not automatically have a matching service name, and a service name does not necessarily match the package name. For example, the SendGrid package is loaded as @sendgrid/mail, while its Connection-backed service name is sendgrid. Use only the service names listed above with this function.

For credentials stored in an API Key Connection, use the documented $io.system.apiKeyInfo function rather than treating the Connection as an SDK object.

For the function parameters and output behavior, see $io.system.sdkLibraryObjectFromConnection.

Loading Node.js Modules with require(...) ​

Cloud Flow custom code supports CommonJS-style require(...) for modules available in ioLoop's curated runtime allowlist.

For example:

js
const axios = require('axios');
const { google } = require('googleapis');

Use require(...) for supported module loading. Do not assume that ES module import statements, dynamic import(), arbitrary filesystem package resolution, or Project-level npm installation are supported.

A package being familiar from standard Node.js development does not mean it is available in Cloud Flow. Verify that the package is supported, and check the version and API surface before using a particular feature.

Curated third-party packages ​

The documented package list includes:

PackageCommon Use
axiosHTTP client operations
xml2jsXML parsing and conversion
csv-parserParsing streamed CSV data
cheerioParsing and traversing HTML on the server
aws-sdkAWS SDK v2 functionality
@aws-sdk/client-s3AWS SDK v3 S3 client functionality
openaiOpenAI SDK operations
stripeStripe SDK operations
@sendgrid/mailSendGrid mail helper
@sendgrid/clientSendGrid API client
twilioTwilio SDK operations
googleapisGoogle API clients
squareSquare SDK operations
node-sshSSH client functionality
momentDate and time utilities
tinifyTinify image compression API

These are supported package names, not a promise that every release or feature of the corresponding public npm package is available. Consult the package's own documentation for its method usage and test it in Cloud Flow's runtime.

Available Node.js core modules ​

Selected core modules include:

  • util
  • url
  • readline
  • string_decoder
  • stream

Do not assume unrestricted access to other built-in modules, operating-system paths, processes, or local files. For Project file operations, prefer the documented $io.fs Server API and relevant Cloud Flow file blocks.

Choosing Between Connection APIs and Direct SDKs ​

For integrations, there are several supported approaches:

ApproachAppropriate Use
Connection blocksStandard visual operations that the configured service exposes.
$io.system.connectionCommand(...)Supported connection commands invoked from server-side code.
$io.system.connectionMethod(...)Supported connection methods invoked from server-side code.
Integration-specific $io.* APIsService functionality wrapped by ioLoop's Server API.
sdkLibraryObjectFromConnection(...)Advanced supported SDK operations using credentials from a configured Connection.
Curated SDK with require(...)Additional library behavior where available and configured appropriately.

Use a supported ioLoop API when it expresses the operation clearly. Use an SDK directly when the required capability is not exposed by the higher-level API, provided the runtime and Connection configuration support that approach.

An SDK package and its Connection are different things: the package provides library functionality, while the Connection provides the configured service identity, authorization, and credentials. Loading a package alone does not configure its authentication.

Integration-Specific Server APIs ​

ioLoop also provides server API namespaces for supported integrations. Examples include:

Availability and supported operations vary by integration. Use these references for exact function signatures. Product-facing Connection setup belongs in Integrations.

Asynchronous Code and Error Handling ​

Database operations, HTTP requests, and many SDK methods complete asynchronously.

When a function returns a Promise, wait for the result before using its data or reporting success. Use await in an appropriate asynchronous Custom Code context and handle errors with try/catch where needed.

For example, when performing an authenticated Google Drive operation:

js
const drive = $io.system.sdkLibraryObjectFromConnection(
  'google.drive',
  'my-google-connection'
);

try {
  const response = await drive.files.list({
    pageSize: 10,
    fields: 'files(id,name)'
  });

  const files = response.data.files || [];
  // Process the list of files as required by this workflow.
} catch (error) {
  // Handle the provider failure and return an appropriate workflow result.
}

This example assumes the selected Google Connection is authorized for the requested Drive operation. SDK behavior and response types are determined by the relevant SDK.

Handle errors at the level that owns the operation. Avoid swallowing errors silently or continuing to update Project records as though an external call succeeded when it did not.

If an operation can be repeated, also consider timeouts, retries, provider rate limits, and duplicate side effects. A retry should not unintentionally create a second payment, order, or notification.

Runtime Timers and Shared Behavior ​

Background Tasks have no separate trigger or scheduling configuration. Their behavior is defined by the logic inside the module.

For example, a Background Task can use the documented $io.system.createTimer(...) and $io.system.reArmTimer(...) APIs to implement periodic behavior. createTimer creates a one-shot timer; repeating execution requires explicitly rearming it.

Background Tasks can also provide shared helpers or values to other backend modules using Flow Share. Shared runtime data is not durable Project storage and should be initialized appropriately when the runtime starts.

For details, see Background Tasks and Flow Share.

Security and Execution Boundaries ​

Although Cloud Flow executes server-side, custom code still needs explicit authorization, input validation, and careful credential handling.

  • Validate caller input. Do not trust browser-provided record IDs, usernames, role values, or Web Hook payloads as proof of authorization.
  • Use Connections for credentials. Prefer central credential management instead of hardcoding tokens or private keys.
  • Enforce sensitive rules on the server. Check the actual caller and relevant data before privileged operations.
  • Return minimum necessary data. Avoid exposing internal provider responses, private file references, or protected Database fields.
  • Log cautiously. Avoid logging secrets or unnecessarily including private customer data.
  • Use supported file APIs. Do not assume unrestricted local filesystem access.

Server-side execution makes trusted processing possible; it does not automatically make every custom workflow secure.

For access controls and caller validation, see Access Security.

Testing and Publishing ​

Save Cloud Flow before testing so its generated runtime JavaScript reflects the latest edits. Then test through the actual invocation path—such as a Page Flow call, an external Web Hook request, or Background Task logic—and inspect Cloud Flow logs.

Distinguish internal Project Database operations from external service operations:

  • Built-in Database operations during Preview use the development database.
  • The Cloud Flow test runtime has its own development/test context; use the documented runtime checks where behavior must differ by environment.
  • An external Connection may still call a live provider account unless that Connection is configured for a test or sandbox environment.

When testing SDK-based integrations, confirm the correct Connection, permissions, scopes, API mode, and expected request/response behavior. Test failed requests as well as successful ones.

A successful editor save checks code syntax, not whether an SDK authenticates successfully or an external operation completes. Previewing also does not publish changes. Use Publish Project and then Launch Project to verify the released experience.

For detailed testing and logs, see Testing and Logs.

Troubleshooting ​

IssueWhat to Check
Module cannot be loadedConfirm the package name is in the supported allowlist and is loaded with require(...).
Code uses unsupported syntaxCheck whether the code relies on ES module imports, unavailable Node.js features, or invalid JavaScript.
SDK object is unavailableConfirm the Connection exists, its service name is supported by sdkLibraryObjectFromConnection, and the Connection is configured correctly.
Authentication failsCheck the Connection's authorization, scopes, provider account, and test/live configuration.
A provider method is missingCheck the curated library version or returned SDK object's supported API surface.
A Cloud Flow saves but fails at runtimeReview runtime logs, asynchronous completion, access checks, data values, and external service errors.
A shared helper is unavailableVerify Flow Share names, initialization, and module load order.
A timer runs only onceVerify that a timer created with createTimer is rearmed where repetition is intended.
The wrong environment is usedCheck test versus published execution, Database environment, and provider Connection settings.

Good Practices ​

  • Start with ioLoop capabilities. Use blocks and Server APIs for supported Project-aware operations.
  • Use require(...) deliberately. Load only supported modules, and do not assume arbitrary npm packages can be installed.
  • Prefer Connections for credentials. Use authenticated SDK objects where supported.
  • Distinguish package availability from SDK helper support. Not every allowed package has a Connection-backed SDK factory.
  • Keep logic maintainable. Use readable JavaScript and clear workflow steps on the canvas.
  • Handle asynchronous work completely. Check success, error, retries, and possible duplicate effects.
  • Respect server-side security responsibilities. Validate inputs and enforce trusted authorization rules.
  • Test the real environment. Review Cloud Flow logs and external service behavior before publishing.

Common Mistakes ​

Avoid these patterns:

  • Assuming Cloud Flow provides an unrestricted Node.js or npm environment.
  • Using unsupported module imports instead of the allowed require(...) interface.
  • Assuming every curated SDK can be obtained through sdkLibraryObjectFromConnection.
  • Hardcoding credentials or copying provider secrets into logs.
  • Using browser-only APIs such as window or document in server-side code.
  • Accessing unsupported Node.js core modules or filesystem paths.
  • Using a Code Expression for a multi-statement program.
  • Assuming let or const declarations in one Custom Code block are automatically shared with another block.
  • Ignoring Promise results or showing success before an external operation finishes.
  • Assuming Background Tasks have external scheduling settings rather than implementing their own logic.
  • Testing an integration only against a success case or assuming Preview automatically switches external providers into sandbox mode.

Cloud Flow custom code is most effective when the runtime's Server APIs, Connections, curated libraries, and visual blocks are used together intentionally, giving each responsibility a clear place in the backend implementation.

Technical Reference ​