What you'll understand by the end
Imagine a temperature sensor reading 24.6 °C. You want to display that number on a dashboard, save it to a file, and send an alert if the room gets too hot. You could write all of that as one large program. Or you could connect small, focused building blocks that each do one job. That second approach is the idea behind Node-RED.
Node-RED is a flow-based programming tool for connecting devices, APIs, services and data. Instead of writing every step as code, you arrange nodes on a canvas and connect them into flows. When data moves through a flow, it is usually carried in a message object. One of the most important properties in that message is msg.payload.
This guide builds those ideas from the ground up. You will see what Node-RED is, how nodes and wires work, what a message looks like, why msg.payload matters, and how a tiny example becomes a useful automation. You do not need to know JavaScript to understand the fundamentals.
What is Node-RED?
Node-RED is an open-source, flow-based programming tool for connecting devices, APIs, services and data. In its browser-based editor, you arrange nodes on a canvas and connect them into flows. When deployed, the Node-RED runtime executes the flow and passes messages between nodes.
A home-monitoring flow might receive a temperature reading over MQTT, convert it to a number, check a threshold, then update a dashboard or send an alert. Common uses include IoT dashboards, protocol bridging, home automation, API integration and rapid prototyping.
Node-RED is not microcontroller firmware or a sensor. It usually runs on a computer, Raspberry Pi or server. An ESP32 can send readings to Node-RED, but its own firmware still handles the device and sensor.
1. What is a node?
A node is a component that performs a task: create a message, receive data, change a value, make a decision or send information elsewhere. Common nodes include:
- Inject: starts a flow manually or on a schedule.
- Debug: displays messages in the Debug sidebar.
- Change: sets, moves or removes message properties without code.
- Switch: routes messages according to rules.
- Function: runs custom JavaScript.
- MQTT In: receives messages from an MQTT topic.
- HTTP Request: makes a web request.
Configure each node for its job. For example, Inject can send the number 24.6; Switch can test whether msg.payload is greater than 30.
A node's right connector is generally an output port, and its left connector an input port. Drag from output to input to create a wire. Wires represent message routes, not physical electrical connections. One output can often feed multiple nodes, and multiple outputs can create branches.
2. What is a flow?
A flow is a connected set of nodes that work together. It can be as small as two nodes or include branches, error handling, storage and dashboards.
[Inject] ─────▶ [Debug]
creates shows the
a message message
Clicking Inject sends a message; Debug displays the selected part of it. A realistic flow might receive an MQTT message, convert its payload to a number, check a threshold and send the result to a dashboard or alert.
Keep the terms distinct: nodes perform individual steps, flows define the connected logic, and messages carry data through it. Click Deploy to apply editor changes to the running runtime. If a rule or wire appears not to work, confirm you deployed and check node status and Debug output.
3. What is a message in Node-RED?
Nodes communicate by passing message objects. A message commonly includes a _msgid identifier and a payload property for the main data. Other properties can hold a topic, timestamp, device name or processing details.
{
"topic": "lab/temperature",
"payload": 24.6,
"unit": "°C"
}
This simplified example represents a temperature reading of 24.6 °C. A real message may include additional properties.
The payload is often the main content; the topic identifies what it refers to. For example, lab/temperature might carry 24.6, while lab/humidity carries 48. This is a convention, not a universal rule—inspect the messages your flow receives.
4. What exactly is msg.payload?
msg.payload means the payload property on a message object named msg. In a Function node, msg is the conventional variable name and the dot accesses a property.
msg.payload = 24.6;
Payloads can be numbers, strings ("hello"), Booleans (true), objects, arrays, buffers or other values produced by a node.
Types matter. The string "24.6" is text; 24.6 is a number. A numeric comparison may behave unexpectedly if incoming data has not been converted. Use Debug to inspect the value and message structure. payload is not a reserved JavaScript keyword; it is simply a widely used property name in Node-RED messages.
5. Build your first flow: Inject → Debug
- Drag an Inject node onto the workspace. Set its payload type to number and value to
24.6. If available, set its topic tolab/temperature. - Add a Debug node and configure it to display
msg.payload. - Connect Inject's output to Debug's input and click Deploy.
- Click Inject's small button and open the Debug sidebar. You should see
24.6.
Click Inject
▼
[Inject: number 24.6]
▼
[Debug: msg.payload]
▼
Debug sidebar: 24.6
Inject creates a message, the wire routes it, and Debug displays its payload.
If nothing appears: confirm you deployed, check the wire, open the Debug sidebar, ensure Debug is enabled, and verify it displays msg.payload or the complete message.
6. Change a message and make a decision
Once you can inspect a message, you can transform it. Node-RED includes core nodes such as Change and Switch that let you perform common operations without writing code.
Imagine the payload is a temperature reading of 32. A Change node can set a new property, move a property, or replace the payload. A Switch node can test a property and route the message to a matching output. For example, set a rule to check whether msg.payload is greater than 30.
[Inject: 32] ─▶ [Switch: msg.payload > 30?]
│
┌────────────┴────────────┐
▼ ▼
[Above threshold] [Normal range]
A Switch node does not magically know what a temperature means. You define the property and rule. If the payload is a string, missing, or an object instead of a number, the rule may not behave as intended. Check the incoming type and convert it where necessary before comparing values.
For a beginner exercise, set the Inject node to send the number 32, configure a Switch node to test msg.payload against 30, and connect each output to its own Debug node. Deploy and click Inject. Then try 25. Observe which path receives each message. This is a simple foundation for threshold alerts, status indicators and automation logic.
7. When should you use a Function node?
Built-in nodes are often enough for simple transformations and rules. When you need custom logic, a Function node lets you write JavaScript. Inside the Function node, the incoming message is conventionally available as msg.
For example, if msg.payload contains a number or a numeric string, this Function node can add a Fahrenheit reading without replacing the original Celsius value:
const raw = msg.payload;
const celsius = typeof raw === "number"
? raw
: (typeof raw === "string" && raw.trim() !== "" ? Number(raw) : NaN);
if (!Number.isFinite(celsius)) {
node.warn("Payload is not a valid temperature number");
return null;
}
msg.temperatureC = celsius;
msg.temperatureF = (celsius * 9 / 5) + 32;
return msg;
This checks the input type before converting it. That matters because JavaScript would otherwise convert values such as null or an empty string to 0, which could look like a real temperature. If the payload is not a valid number, the Function node warns and stops that message by returning null.
After this Function node, the message might contain:
{
"payload": 24.6,
"temperatureC": 24.6,
"temperatureF": 76.28
}
This is a simplified illustration of the relevant properties; the real message may contain additional fields. Notice that we did not overwrite msg.payload. Keeping the original value can be useful when other nodes still need it. Alternatively, you can intentionally set msg.payload to a transformed result when that is what the next node expects.
Good habit: use a Change or Switch node when it expresses the task clearly; use a Function node when the logic genuinely needs code. Keep functions short, validate external data, and return the message when you want the flow to continue.
8. How Node-RED fits into an IoT project
A common architecture is to let a microcontroller handle the physical world while Node-RED handles data routing and automation. For example, an ESP32 reads a sensor and publishes a message using MQTT. Node-RED subscribes to the relevant topic, inspects the incoming message, and sends the reading to a dashboard or database.
[Sensor] → [ESP32 firmware] → MQTT broker → [Node-RED flow]
├──▶ [Dashboard]
├──▶ [Database]
└──▶ [Alert rule]
Each piece has a different job:
- Sensor: measures a physical quantity.
- ESP32 firmware: reads the sensor and publishes data.
- MQTT broker: receives and forwards messages between clients.
- Node-RED: processes messages and connects systems together.
- Dashboard/database/notification service: presents or stores the result, or informs someone when a rule is met.
Node-RED can also communicate using other integrations, including HTTP and serial, depending on the nodes and environment you configure. MQTT is common in IoT because publishers and subscribers do not need to connect directly to one another; they communicate through a broker.
Remember that a flow editor does not remove the need for sound system design. Consider network loss, stale readings, authentication, retained MQTT messages, duplicate events and what should happen when a device stops reporting. For control of physical equipment, make sure critical safety behaviour remains local to the device or a properly designed controller rather than depending entirely on a dashboard or an internet connection.
9. Common beginner mistakes
“The Debug sidebar shows undefined.”
The selected property may not exist, or an earlier node may have changed it. Display the complete message and inspect its structure. The value may be nested, such as msg.payload.temperature.
“My number comparison does not work.”
The payload may be text rather than a number. Inspect the incoming value and convert it before comparing.
“The flow looks right, but nothing happens.”
Deploy the latest changes, trigger the input, and check node status and Debug output. For MQTT, verify the broker connection, topic and message format.
“I lost the original value.”
A node may have overwritten msg.payload. Preserve it in another property first if downstream nodes still need it.
“A node is missing.”
Some nodes require separately installed packages. Check compatibility and install only trusted, maintained packages.
“It stops working when the network drops.”
Add suitable status checks, timeouts, retries and error handling. Consider timestamps or stale-data checks so old readings are not mistaken for current ones.
10. Best practices for flows you can maintain
A small flow is easy to understand. As it grows, a few habits make a major difference:
- Name nodes clearly.
Parse temperature JSONis more useful thanfunction 3. - Label important wires or branches where useful. Make the intention visible to the next person who opens the flow.
- Inspect data at boundaries. Use Debug nodes while developing, especially after MQTT, HTTP and parsing steps. Remove noisy debug output when it is no longer needed.
- Validate external input. Network messages may be malformed, incomplete, stale or unexpected. Check types and required fields before using them.
- Handle errors deliberately. Use appropriate error-handling patterns and test what happens when a service is unavailable.
- Protect the editor and services. Do not expose a Node-RED editor or control endpoint to the public internet without proper authentication, access controls and secure network configuration. Treat credentials and tokens as secrets.
- Keep flows understandable. Split complex tasks into logical sections and document non-obvious assumptions.
- Test failure cases. Try empty payloads, unexpected strings, delayed messages and disconnected services—not just the happy path.
Node-RED makes integrations quicker to assemble, but visual programming is still programming. Reliable results come from clear data contracts, defensive handling and testing, not just connecting nodes until the lines look right.
Frequently asked questions
Is Node-RED suitable for beginners?
Yes. Inject, Debug, Change and Switch nodes let you learn the basics before writing JavaScript.
Is Node-RED free?
Node-RED is open-source software, though hosting, hardware and external services may cost money.
Does Node-RED run on an ESP32?
Usually it runs on a computer, Raspberry Pi or server. The ESP32 communicates with it through MQTT, HTTP, serial or another supported integration.
Do I have to use msg.payload?
No. It is common, but messages can carry data in other properties.
Is Node-RED the same as MQTT?
No. MQTT is a messaging protocol; Node-RED is a tool that can publish, subscribe to, transform and route MQTT messages.
Do I need JavaScript?
Not to begin. It helps when built-in nodes cannot clearly express the logic you need.
The idea to remember
Node-RED becomes much easier once you separate three things in your mind: nodes do the work, flows define the route, and messages carry the data. msg.payload is simply the commonly used property where that message's main value is stored.
Start with Inject → Debug. Change the payload from a number to a string, inspect the full message, then add a Switch node and route values down different paths. Those small experiments teach the mental model behind much larger IoT systems.
When you connect a real ESP32 or sensor later, the same model still applies: data arrives, nodes inspect or transform it, and the flow sends it where it needs to go. That is the real power of Node-RED—not that it eliminates programming, but that it makes the movement and transformation of data visible.
Suggested next steps
- Learn how an ESP32 publishes sensor readings using MQTT.
- Build a simple MQTT broker and connect a Node-RED MQTT In node.
- Create a dashboard for temperature and humidity readings.
- Add a threshold rule and test what happens when the sensor stops reporting.
Editorial note: Add the final original diagrams and screenshots in the image placeholders before publication. Verify the Node-RED editor screenshots against the version you use, as node configuration panels can change between releases.