Advice on communication between multiple Node-RED instances (or external apps)

Hi everyone,

Following some great suggestions here in the forum, I've been using MQTT for almost everything within Node-RED — and it's been working well in general.

However, I recently ran into a challenge that I can’t quite resolve, and I’d really appreciate some advice.


The context:

I have a main Node-RED instance running on an embedded device. Due to resource constraints, I can't deploy this main instance frequently — especially because deploying resets the process, and some critical modules are still in development/debug mode.

To work around this, I run a second Node-RED instance for development purposes, so I can deploy freely and test flows. I use MQTT to exchange messages between the instances, and that has worked fine.

Now things have scaled up — I’m running five Node-RED instances in total — and I’ve started losing control over MQTT traffic. It's becoming difficult to track where each message is coming from and where it’s going.


The dilemma:

To simplify things, I’m considering replacing some of these secondary Node-RED instances with lightweight code (e.g. Python, Java, C, or Rust). This raises two key questions:

  1. Should I replace MQTT with a more direct communication method, like named pipes, UNIX sockets, or something else more tightly coupled? What would be a reliable and lightweight way to exchange messages between these apps and Node-RED?

  2. I know I could use Bash to run external programs and parse results, but it doesn’t feel right. Ideally, I’d like to implement async tasks (in Python, Rust, etc.) that can share info with Node-RED efficiently.
    In my mind, the ideal would be to have "just another node" — a node that does a lot of heavy-lifting externally, while still integrating cleanly with the flow.


I feel like I might be missing a better architectural perspective here. Any insights, real-world experiences, or suggestions would be greatly appreciated.

Thanks!

Why don’t you add the name of the device publishing the mqtt msg. Then you can see what device it came from.

I do this with 5 pi’s running. Each one sends environmental data and the name of the pi sending it.

I also have several devices (esp32-s2-mini’s) that send temp/humidity/pressure and the device’s name via mqtt so I can tell where the data came from

Surely this can be eliminated by appropriate MQTT topic structures, for example make the first part of every topic the originating machine name: moonbase1/temperature/external

I have considered having just one mqtt-out node per device, on a flow which all other flows can link to.
This could include such features as guaranteed delivery & maybe tacking system telemetry such as clock time, IP address, uptime onto every message.

That works where the original message comes direct from a device. It doesn’t always help when the message(s) come from Node-RED. I’m with Paul on this one, I add extra messages, usually to sub-topics, that record the part of my flows (and the NR instance in this case) and the timestamp of the last update.

I wouldn’t - in general. But you may well have specific requirements where a different comms method might be better. For example, I have several batch jobs that run via CRON and they call a Node-RED endpoint effectively as a REST API.

But tight coupling is generally a long-term pain in the posterior to maintain. I’d only do it if I had to. Thankfully, Node-RED supports ALL of the method you mention and far more besides :smiley:

Though it is very extensive, Node-RED is still a node.js microservice app at heart. And any of the platforms you mention would be the same when running a long-running task. Interactions between microservices ARE best kept loosely coupled where possible as it allows you to more easily rip and replace services.

In my view, Node-RED isn’t an especially good “orchestrator” of microservices. You can almost certainly do it but I don’t believe that is one of its strengths.

The architectural viewpoint here would be that you should be DOCUMENTING:

  1. Your high-level architecture - e.g. the components and how they interact.
  2. Your data-flows.

This helps you not only understand the big picture but it also helps you stay on-track as you continue to develop.

I use the MQTT5 extensions (which mosquitto and node-red support) to add a property to the message indicating the source machine. This has the advantage that it does not change the basic MQTT message (topic and payload), so can be added to existing flows with zero side effects.
To do this all you need to do is to tell node-red that the broker can use MQTT5 and configure the broker like this


Note the user properties at the bottom.

Alternatively you can pass in the source (and any other properties you might want to include, timestamp for example) by passing in msg.userProperties.source with the machine name.

3 Likes

Without a doubt, I need to keep using MQTT for communication.

Migrating to MQTT 5 is still not an option due to incompatibility with some microcontrollers and the difficulty I’d face trying to update and debug them.

Clearly, I need to revisit and better structure how I’m publishing my messages.

Since I’ve already received a lot of great input, let me share a practical problem — I’d really appreciate your feedback.

I have several machines distributed throughout the site — up to 40 units. Each group of 4 has a gateway that publishes to MQTT. Currently, I use the same topic for all of them, so in Node-RED I just subscribe to driver/+.

Still, should I split them into:

gateway1/driver/+

gateway2/driver/+

gateway3/driver/+

And then aggregate and republish?

It would add an extra step — perhaps an unnecessary one?

Yes, use those modified topics.
Subscribe to +/driver/+ (unless you only want the messages from a single device)

Or you might prefer driver/whatever/gateway1, in which case subscribing to driver/+/# still gets messages from devices whose topic you have not yet changed.

That need not be necessary. You can subscribe to the microcontroller's topics in node-red and republish them with meaningful topics with additional user properties as required. For example, my kitchen temperature comes in embedded in the topic home/we01/state. I extract it and publish it as home/kitchen/temperature adding the source we01 to the MQTT5 user properties. All other logic accesses it via home/kitchen/temperature so if I were to change the sensor type so its native topic was different, then it would only affect the republish code and nothing else.

Got it! I haven’t migrated my broker yet, but I’m going to give it a try.

Are you using Mosquitto too?

Certainly, and have been doing so on multiple machines for many years. I don't remember ever having any significant issues.

Most of us use Mosquitto. It is solid, reliable, performant with low resource requirements.