Change, JSONata, or Function: Choosing a Node-RED Message Transformation Node
Choose Change for simple property moves, JSONata for read-only transforms, and Function only for complex logic in Node-RED flows.
04 Jul 2026, 07:55 UTC

State the decision and constraints
When a Node-RED flow receives a message, the message travels as a JavaScript object conventionally called msg. The payload property usually holds the data you want to change, while properties such as topic carry metadata. You must choose among three built-in nodes to reshape that data: Change, JSONata, and Function.
Use this decision:
- Change node: move, copy, set, or delete a property, or apply a simple regular expression.
- JSONata expression: read-only mapping, filtering, or computation across fields.
- Function node: arbitrary JavaScript, loops, external modules, or side effects such as writing to context.
Constraints to keep in mind:
- Maintainability: flows should remain auditable without reading custom code.
- Security: avoid untrusted JavaScript in Function nodes.
- Resources: Node-RED runs on a single event loop, so poorly written JavaScript can freeze all flows on embedded hosts.
Compare the supported options
| Node | Best for | Limitations |
|---|---|---|
| Change | Set, move, copy, or delete msg properties; simple regex | Cannot compute values across multiple fields or branch on conditions |
| JSONata | Transform, map, filter, or compute values from an existing payload | Read-only expression language; cannot modify msg outside the assigned property or call Node-RED runtime APIs |
| Function | Loops, custom JavaScript, npm modules, or side effects | Harder to audit and visually debug; can block the Node-RED event loop if poorly written |
Trade-offs
The Change node is fastest to configure and easiest to review, but it cannot combine two fields into a new value. JSONata keeps logic declarative and side-effect free, yet debugging a long expression is harder than stepping through JavaScript. The Function node offers full JavaScript power, but it breaks visual debugging, requires careful error handling, and can block Node-RED's single-threaded event loop if it contains long-running or synchronous work.
Concrete implementation: reshape an IoT payload
Suppose a device sends this message:
{ "deviceId": "sensor-01", "status": "ok" }
Goal: set msg.topic from deviceId, convert status to uppercase, and inspect the result.
- Drag an Inject node onto the canvas. Set its output type to JSON and paste the sample object above.
- Drag a Change node. Add a rule: Set
msg.topictomsg.payload.deviceId. - Drag a second Change node. Set its rule type to JSONata expression. Set
msg.payloadto$uppercase(payload.status). - Drag a Debug node. Configure it to output the complete
msgobject. - Wire the nodes in order: Inject to the first Change node, to the second Change node, to Debug.
- Deploy the flow.
Expected result after clicking the Inject button: msg.topic is sensor-01 and msg.payload is OK. The original deviceId is preserved in topic even though payload was overwritten.
Limitations and how to check the result
JSONata expressions cannot modify msg outside the property you assign, and they have no access to Node-RED runtime APIs. Function node code is not sandboxed by default, so review third-party code before deploying. Never store secrets or credentials in msg properties; use Node-RED credentials configuration and environment variables instead.
Rollback after deployment
Deploying changes the running runtime. If the new flow misbehaves, use the editor's undo or re-import the previously exported flow JSON and redeploy.
Version assumptions
Behavior described here applies to Node-RED 3.x LTS and current 4.x releases. JSONata is built-in. Access to external npm modules from a Function node depends on the functionExternalModules setting in settings.js; editing that file requires file-system access to the Node-RED installation directory and a restart of Node-RED.
Practical verification
- Open the Node-RED editor, select the menu, and choose About to confirm the version.
- Deploy the flow.
- Click the Inject node button.
- Open the Debug sidebar and inspect the message.
- Confirm
msg.topicissensor-01andmsg.payloadisOK. - Export the flow to JSON and store it in version control for peer review.
0 replies
A thoughtful contribution can make all the difference. Be the first to share one.