Skip to content

Worker Function Node

Overview

The Worker Function node allows you to execute JavaScript code in a separate worker thread, enabling non-blocking operations that won't freeze the Node-RED runtime. This is particularly useful for CPU-intensive tasks or operations that might take a significant amount of time to complete.

Key Features

  • Non-blocking execution: Runs code in a separate worker thread using Node.js Worker Threads API
  • Queue management: Automatically queues incoming messages when the worker is busy
  • Buffer handling: Efficiently handles binary data using SharedArrayBuffer
  • Lifecycle hooks: Provides initialization and finalization code sections
  • Module support: Can require and use external npm modules

Configuration

Properties

Name

  • Type: String
  • Optional: Yes
  • Description: A custom name for the node instance

Number of Outputs

  • Type: Number
  • Default: 1
  • Range: 1-10
  • Description: Number of output ports for the node

Delay (ms)

  • Type: Number
  • Default: 0
  • Description: Time delay in milliseconds before processing each message. Useful for rate limiting or throttling operations.

Code Sections

The node provides three separate code editors accessible via tabs:

On Start (Init)

Code that executes once when the node is deployed or started. Useful for:

  • Initializing variables
  • Setting up connections
  • Loading resources
javascript
// Example: Initialize a counter
var processedCount = 0;

On Message (Function)

The main processing function that executes for each incoming message. This code runs in the worker thread.

Available objects:

  • msg: The incoming message object
  • node: Object with methods:
    • node.send(msg): Send a message to the output
    • node.error(err): Report an error

Return value:

  • Returning a message object will automatically send it to the output
  • Use node.send() for more control or to send multiple messages
javascript
// Example: Process image data
const processedData = heavyImageProcessing(msg.payload);
msg.payload = processedData;
return msg;

On Close (Final)

Code that executes when the node is stopped or re-deployed. Useful for:

  • Cleanup operations
  • Closing connections
  • Releasing resources
javascript
// Example: Log statistics
console.log('Total messages processed:', processedCount);

Input

The node accepts any message object. Special handling for binary data:

  • Buffer objects are automatically converted to SharedArrayBuffer for efficient transfer to the worker thread
  • The worker thread automatically converts them back to Buffer for processing

Output

The node outputs the message returned by the function code or sent via node.send().

Usage Examples

Example 1: CPU-Intensive Calculation

javascript
// Function code
function fibonacci(n) {
    if (n <= 1) return n;
    return fibonacci(n - 1) + fibonacci(n - 2);
}

const result = fibonacci(msg.payload.number);
msg.payload = { result: result };
return msg;

Example 2: Image Processing with Buffers

javascript
// Function code
// Assuming msg.payload contains image buffer
const imageBuffer = Buffer.from(msg.payload);

// Perform image processing (placeholder)
// const processed = someImageLibrary.process(imageBuffer);

msg.payload = imageBuffer;
return msg;

Example 3: Using External Modules

First, ensure the module is installed in your Node-RED environment:

bash
npm install sharp

Then in the function code:

javascript
const sharp = require('sharp');

// Resize an image
sharp(msg.payload)
    .resize(200, 200)
    .toBuffer()
    .then(buffer => {
        msg.payload = buffer;
        node.send(msg);
    })
    .catch(err => {
        node.error(err);
    });

// Don't return anything when using async operations

Example 4: Delayed Processing with Queue

Configure delay to 1000ms (1 second):

javascript
// Function code
msg.payload = {
    processed: true,
    timestamp: Date.now()
};
return msg;

Messages will be processed one per second, even if they arrive faster.

Technical Details

Worker Thread Architecture

The node creates a single worker thread that:

  1. Accepts messages from the main thread
  2. Executes the function code
  3. Returns results to the main thread
  4. Processes queued messages sequentially

Queue Behavior

  • Messages are queued when the worker is busy
  • Queue is processed FIFO (First In, First Out)
  • The configured delay applies between message processing

Buffer Handling

  • Input buffers are converted to SharedArrayBuffer for zero-copy transfer
  • Worker thread receives the data as Buffer
  • Output buffers are transferred back using transferable objects for efficiency

Module Resolution

The worker thread inherits the module search paths from the parent process, allowing it to require the same modules available to Node-RED.

Error Handling

Errors in the function code are caught and reported via:

  • Node-RED debug panel
  • Console logs (prefixed with "Worker caught error:")
  • The node's error output
javascript
// Example: Proper error handling
try {
    const result = riskyOperation(msg.payload);
    msg.payload = result;
    return msg;
} catch (err) {
    node.error('Operation failed: ' + err.message);
    // Optionally return error in message
    msg.error = err.message;
    return msg;
}

Performance Considerations

When to Use Worker Function

Good use cases:

  • CPU-intensive computations (image processing, data analysis)
  • Operations that block the event loop
  • Processing large datasets
  • Complex mathematical calculations

Not recommended for:

  • Simple data transformations (use regular function node)
  • I/O operations (already non-blocking in Node.js)
  • Very frequent small operations (overhead of worker communication)

Optimization Tips

  1. Minimize data transfer: Only send necessary data to the worker
  2. Batch processing: Process multiple items in a single message when possible
  3. Use delay wisely: Set appropriate delays to control resource usage
  4. Buffer efficiency: Leverage the built-in buffer handling for binary data
  5. Avoid excessive queuing: Monitor queue size in high-throughput scenarios

Comparison with Standard Function Node

FeatureWorker FunctionStandard Function
ExecutionSeparate threadMain event loop
BlockingNon-blockingCan block if code is slow
ConcurrencySequential (queued)Immediate
Buffer handlingSharedArrayBufferDirect
Module accessYesYes
OverheadHigher (thread communication)Lower

Troubleshooting

Worker exits unexpectedly

  • Check for unhandled exceptions in function code
  • Verify all required modules are installed
  • Review Node-RED logs for error details

Messages not processing

  • Verify function code returns or calls node.send()
  • Check if worker is stuck in an infinite loop
  • Review queue status (check delay configuration)

Buffer data corrupted

  • Ensure proper Buffer handling in function code
  • Verify data types before processing
  • Check for race conditions in async operations

Best Practices

  1. Keep functions focused: One worker function per specific task
  2. Handle errors gracefully: Always use try-catch for risky operations
  3. Test with delays: Verify behavior under high load using the delay setting
  4. Monitor performance: Use Node-RED debug to track execution times
  5. Document complex logic: Add comments in the function code
  6. Clean up resources: Use the finalization code for proper cleanup
  7. Avoid global state: Each message should be independent when possible

See Also