Skip to content

Good Practices

This guide compiles the best practices for designing, implementing, and maintaining workflows in an efficient, secure, and scalable way.


The label of each node is used in dynamic variables with the @ syntax. A node named “Get Customer” allows referencing its data as {{@Get Customer.email}}, which is much more readable than {{#3.email}}.

Bad example:

  • Node 1: “HTTP”
  • Node 2: “Decision”
  • Node 3: “HTTP”

Good example:

  • Node 1: “Get Order”
  • Node 2: “Validate Available Stock”
  • Node 3: “Update Inventory”

Apply the single responsibility principle: each workflow should do one thing and do it well. A workflow that manages orders should not also handle invoicing and sending marketing emails.

Use subWorkflow to split complex workflows

Section titled “Use subWorkflow to split complex workflows”

When a business process requires many steps, split it into several workflows connected through the subWorkflow node. This allows:

  • Reusing common parts across different processes.
  • Testing each part independently.
  • Reducing the visual complexity of the editor.
  • Facilitating teamwork.

Each workflow has a description field. Use it to explain:

  • What the workflow does and why it exists.
  • What system or business process it supports.
  • What triggers activate it.
  • Any external dependencies or prerequisites.

Use dynamic variables with node references

Section titled “Use dynamic variables with node references”

Prefer {{@NodeName.field}} instead of {{field}}. The @ syntax explicitly indicates which node the data comes from.

# Recommended
{{@Get Customer.email}}
{{@Search Order.total}}
# Not recommended
{{email}}
{{total}}

The setVariable and getVariable nodes allow storing data in memory during workflow execution. They are useful for:

  • Storing an authentication token obtained at the start for use in multiple HTTP calls.
  • Keeping a counter or accumulator that is updated in an iterator.
  • Sharing configuration between parallel branches.

Before operating with external data (webhooks, APIs, forms), validate it with a Decision or Validate node. Check that:

  • Required fields exist and are not empty.
  • Data types are correct (numbers, dates, emails).
  • Values are within expected ranges.

Use DataStore to persist data between executions

Section titled “Use DataStore to persist data between executions”

When data needs to survive between different workflow executions, use DataStore. Memory variables only exist during a single execution; DataStore persists data permanently.


Always consider the “false” branch in decisions

Section titled “Always consider the “false” branch in decisions”

Each Decision node has two outputs: true and false. Never leave the false branch unconnected. A Decision node without a connected false branch causes the execution to stop silently.

Use continueOnError for non-critical nodes

Section titled “Use continueOnError for non-critical nodes”

Some nodes can fail without invalidating the entire flow. For example, a node that sends a Slack notification should not stop order processing if Slack is temporarily down.

Reserve this option for truly non-critical nodes. Never enable it on nodes whose result is needed for subsequent steps.

Use notification nodes (SendMail, Slack, Telegram) to alert the team when critical errors occur. Include:

  • Name of the workflow and node that failed.
  • Error message.
  • Relevant data to diagnose the problem.
  • Execution timestamp.

Periodically review the traces table to:

  • Detect workflows that fail recurrently.
  • Identify performance bottlenecks.
  • Verify that scheduled workflows execute as expected.
  • Audit the processing of sensitive data.

When using the Iterator node with the maxConcurrent option, control how many iterations run in parallel. A value between 3 and 10 is usually adequate for most external APIs.

When you need to save or update many records, use DataStore’s bulk operations instead of saving record by record inside an iterator. Bulk operations are significantly faster for large volumes.

When implementing loops, always ensure there is a clear exit condition and a maximum iteration limit as a safeguard.

When a workflow calls external APIs with request limits, insert Delay nodes between calls to respect those limits.


Never put credentials directly in the configuration

Section titled “Never put credentials directly in the configuration”

Always use the platform’s credential system, which:

  • Stores credentials in encrypted form.
  • Allows reusing them across multiple nodes and workflows.
  • Facilitates rotation without modifying workflows.
  • Prevents credentials from appearing in traces or logs.

Webhooks are public entry points. Before processing received data:

  • Verify the origin’s authenticity (tokens, signatures, headers).
  • Validate the structure and content of the data.
  • Sanitize data to prevent injections.
  • Reject requests that do not comply with the expected format.

Separate development and production environments

Section titled “Separate development and production environments”

Use the development webhook for testing and the production one for real traffic. Never test with production data without anonymizing it.

Apply the principle of least privilege: credentials should have only the permissions necessary for the task they perform.


If the workflow needs to perform long operations, use the Web Response node as soon as possible to confirm receipt:

Webhook -> Web Response (202 Accepted) -> [long processing] -> End
  • Verify tokens or secret keys in headers.
  • Validate HMAC signatures when the sending system provides them.
  • Reject requests with error Web Response (400, 401, 403).

Use a Decision node immediately after the webhook to filter and process only relevant events.

Sending systems may resend the same event. The workflow should detect and handle duplicates:

  • Store already processed event IDs in DataStore.
  • Before processing, check if the event was already handled.
  • If already processed, respond with success without repeating the operation.

Don’t schedule a workflow to run every minute if the task doesn’t require it. Evaluate the actual need.

Schedules run according to the time zone configured on the server. Document the expected time zone in the workflow description.

Verify that the previous execution finished

Section titled “Verify that the previous execution finished”

Use a record in DataStore that indicates whether the workflow is running. At the start, check if the previous execution has finished.

Scheduled workflows run without human intervention. Implement audit logging with start, end, record count, and errors.


Use {{@NodeName.field}} to reference specific nodes

Section titled “Use {{@NodeName.field}} to reference specific nodes”
{{@Get Customer.name}} -> Clear: the name comes from the "Get Customer" node
{{@Calculate Price.total}} -> Clear: the total comes from the "Calculate Price" node

If nodes are rearranged, name-based references still work.

Use {{var.name}} for data shared between workflows

Section titled “Use {{var.name}} for data shared between workflows”

They allow passing configuration, parameters, or results between execution levels without needing to map each field individually.

Use {{#1.field}} only when relative position is relevant

Section titled “Use {{#1.field}} only when relative position is relevant”

Useful inside iterators where you always want to reference the immediately previous node. In most cases, name-based reference is preferable.

Verify that all dynamic variables resolve correctly before activating in production.


Organize data using groups that reflect the business structure:

  • customers - customer and contact data.
  • orders - orders and their statuses.
  • configuration - system parameters and options.
  • cache - temporary data from external APIs.

Keys should be identifiers with business meaning: email for customers, order_id for orders, sku for products.

Tags allow adding metadata to facilitate searches: mark processing status, categorize records, group by batch or execution.

Use DataStore Trigger to react to changes in real time

Section titled “Use DataStore Trigger to react to changes in real time”

It is more efficient than a scheduled workflow that periodically checks for changes.

Create a scheduled workflow that deletes old records, archives historical data, and cleans up expired cache records.


Validate before processing

When to use it: When an external system needs to send data and wait for a synchronous response.


Scheduled ETL

When to use it: For periodic synchronizations, imports, migrations, aggregated reports.


List and detail with iterator

When to use it: For processing lists where each element requires an individual operation.


Approval request

When to use it: For expense approval processes, vacation requests, publication approvals.


Sync with upsert

When to use it: To keep two systems synchronized (CRM and ERP, online store and warehouse).


Route alerts by type

When to use it: For alert systems where urgency determines the channels used.


  1. Clarity: Name nodes well, document workflows, use variables with explicit references.
  2. Robustness: Validate input data, handle the false branch, implement error notifications.
  3. Efficiency: Control concurrency, use bulk operations, choose reasonable schedule intervals.
  4. Security: Use the credential system, validate webhooks, apply least privilege.
  5. Maintainability: Split complex workflows, clean up obsolete data, monitor traces.