npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@rosepetal/node-red-contrib-async-function

v1.0.3

Published

A Node-RED function node that runs code in worker threads to keep your flows responsive

Readme

node-red-contrib-async-function

Run heavy computations in Node-RED without slowing down your flows. This node works like the function node you already know, but keeps things responsive when the work gets heavy.

Example

What You Get

  • Write JavaScript code that feels familiar—same as the function node.
  • Run CPU-intensive tasks without blocking other flows.
  • See real-time stats showing active workers and queue depth.
  • Configure worker pools to match your workload.
  • Handle bursts of messages smoothly with automatic queuing.
  • Add external npm modules with auto-installation support.

Before You Start

  • Node.js 18 or newer (worker threads need it).
  • Node-RED 2.0 or newer.

How It Works

Drop an async function node into your flow. Write your code just like you would in a regular function node. The difference? Your code runs in a separate worker thread by default (or a child process if configured), so heavy operations won't freeze Node-RED.

When to Use This

Great For:

  • Calculating prime numbers, running crypto operations, or processing large datasets.
  • Tasks that take more than 10 milliseconds to finish.
  • Keeping your dashboard and other flows responsive during heavy work.

Skip It For:

  • Simple math or quick transformations (the regular function node is faster).
  • Flows that require live context reads/writes during execution (context is snapshot-based).

Node Options

Code & Behavior

  • Name – Optional label for your canvas.
  • Function – Your JavaScript code. Works with async/await, return, and require().
  • Outputs – How many output wires (0-10). Return an array for multiple outputs.
  • Timeout – Maximum seconds to wait before killing the worker. Default: 30 seconds.
  • Runtime – Worker Threads (default, fastest) or Child Process (for native modules like gl).

Worker Pool

  • Workers – Fixed number of workers (1-16). Each node maintains exactly this many workers. Default: 3.
  • Queue Size – Messages to queue when all workers are occupied. Default: 100.

Modules

Add external npm modules that will be available in your code. Similar to the standard Node-RED function node's module feature.

  • Module – The npm package name (e.g., lodash, moment, @scope/package).
  • Import as – Variable name to access the module in your code.

Modules are auto-installed to ~/.node-red on first deploy if not already available. Use them directly in your code without require():

// With modules: lodash → _, moment → moment
const doubled = _.map(msg.payload, x => x * 2);
msg.timestamp = moment().format('YYYY-MM-DD');
return msg;

Buffer Handling

  • Buffers – Worker Threads use zero-copy transfer when possible. Child Process mode and non-transferable buffers fall back to shared memory (/dev/shm on Linux, otherwise os.tmpdir()), with base64 fallback if needed.

Typical Flow

  1. Add an async function node to your workspace.
  2. Connect an Inject node (input) and a Debug node (output).
  3. Write a simple script:
    msg.payload = msg.payload * 2;
    return msg;
  4. Deploy and trigger. Watch the status update in real time.

What You Can Use in Your Code

Available:

  • msg – The message object (must be serializable)
  • return – Return a single message or array of messages
  • async/await – For asynchronous operations
  • require() – Load Node.js built-in or installed modules
  • Configured modules – Available directly as variables (no require needed)
  • console – Logging functions
  • setTimeout, setInterval – Timers

Notes:

  • context, flow, global are snapshot-based: reads are from the snapshot, writes are applied after the function completes
  • Snapshot includes only literal keys found in flow.get("key") / global.get("key") / context.get("key")
  • Context store selection is not supported (default store only)
  • node.warn/error/log are collected and forwarded to the main thread
  • Non-serializable objects (functions, symbols, etc.)

Code Examples

Simple Transformation

msg.payload = msg.payload * 2;
return msg;

Using External Modules

Option 1: Configure in Setup tab (recommended)

Add the module in the Modules section of the Setup tab, then use it directly:

// Module configured: lodash → _
msg.payload = _.sortBy(msg.payload, 'name');
return msg;

Option 2: Traditional require()

const crypto = require('crypto');

msg.hash = crypto.createHash('sha256')
    .update(msg.payload)
    .digest('hex');

return msg;

CPU-Intensive Task (Won't Block!)

function isPrime(n) {
    if (n <= 1) return false;
    for (let i = 2; i * i <= n; i++) {
        if (n % i === 0) return false;
    }
    return true;
}

const limit = msg.payload;
const primes = [];

for (let i = 2; i <= limit; i++) {
    if (isPrime(i)) {
        primes.push(i);
    }
}

msg.payload = primes;
return msg;

Multiple Outputs

if (msg.payload > 100) {
    return [msg, null];  // Send to first output
} else {
    return [null, msg];  // Send to second output
}

Status Display

The node shows you what's happening in real time:

  • Active: 2/4 – 2 workers processing out of 4 total
  • Queue: 5 – 5 messages waiting
  • Green dot – Normal operation
  • Yellow dot – Queue filling up (>50 messages)
  • Red dot – Queue almost full (>90%) or error
  • Ring – All workers busy with a backlog

Performance Notes

  • Worker threads add about 5-10ms overhead per message (child process mode is higher).
  • Best for operations taking more than 10ms to run.
  • Each node maintains a fixed pool of workers—no startup delay or dynamic scaling overhead.
  • Workers are dedicated per-node, ensuring predictable performance.
  • Binary Fast Path: Worker threads use zero-copy transfer when possible; shared memory is the fallback.
  • Event loop never blocks, even when processing multi-MB binary data (images, files, etc.).

Error Handling

Errors in your code get caught and sent to a Catch node:

if (!msg.payload) {
    throw new Error('Payload is required');
}

Installation

cd ~/.node-red
npm install @rosepetal/node-red-contrib-async-function

Restart Node-RED and find the node in the function category.

Migration from Earlier Versions

If you're upgrading from a version that used minWorkers and maxWorkers:

  • Your existing flows will automatically migrate to use the new numWorkers parameter
  • The migration uses your previous maxWorkers value as the fixed worker count
  • Check the Node-RED log for migration messages
  • Edit your nodes to see the new simplified "Workers" configuration field
  • Note: The new version uses a fixed worker pool instead of dynamic scaling for more predictable performance

Contributing

Found a bug or have an idea? Open an issue or pull request on GitHub.

License

Apache-2.0 © 2025 Rosepetal


Built by Rosepetal – Making Node-RED flows faster and friendlier.