The Node-RED delay node holds messages back for a set time or releases them at a fixed rate, which makes it the simplest way to tame fast MQTT streams. In this tutorial you will use it to throttle high-frequency sensor data before publishing, rate-limit each topic separately, choose between queueing and dropping, control the queue at runtime and stay comfortably within broker limits.
Why Rate Limiting Matters for MQTT Flows
A sensor sampling every 100 milliseconds produces ten messages a second. Multiply that by a few dozen sensors and Node-RED is pushing hundreds of messages a second towards whatever sits downstream. Often nothing downstream needs that rate:
- Brokers enforce limits. Shared and public brokers cap message rates per client. The free public MQTT broker at
broker.connectmq.com, for example, allows 10 messages per second per client. Exceed it and messages are rejected or the client is throttled. - Dashboards cannot keep up. A browser chart redrawing 50 times a second is unreadable and wastes CPU.
- Databases and APIs charge per write. Writing every raw sample to a cloud database or calling an HTTP API per message gets expensive and can trip API rate limits.
- Notifications annoy people. A temperature hovering around a threshold can generate dozens of alerts a minute.
The Node-RED delay node solves all of these without code.
Delay Node Modes at a Glance
Open a delay node and the Action dropdown offers two families of behaviour:
| Mode | Option | What it does | Typical use |
|---|---|---|---|
| Delay each message | Fixed delay | Holds every message for the same time | Debouncing, sequencing actions |
| Delay each message | Random delay | Holds each message for a random time in a range | Spreading load, simulating devices |
| Delay each message | Override delay with msg.delay |
Uses the delay in milliseconds from the message | Per-message timing |
| Rate limit | All messages | Releases at most N messages per interval | Protecting a broker or API |
| Rate limit | For each msg.topic |
Limits each topic independently, keeping the latest value | Multi-sensor throttling |
Delay mode never drops anything; it only shifts messages in time. Rate limit mode either queues extra messages or drops them, depending on the option you pick.
Queue or Drop: The Decision That Matters
In rate limit mode with All messages, the default is to queue: messages beyond the rate wait in memory and are released one by one. Tick drop intermediate messages and extra messages are discarded instead. Recent Node-RED versions also offer sending intermediate messages to a second output, so you can route the overflow somewhere else, for example to a counter.
Choose by asking whether every message matters:
- Every message matters (commands, events, counts): queue. Make sure the average input rate is below the release rate, or the queue grows forever.
- Only the latest value matters (temperatures, levels, positions): drop, or use per-topic mode. You keep fresh data and memory stays flat.
- You need both: send the overflow to the second output and aggregate it, for example into an average.
A queue that grows without bound is the classic delay node failure. If producers outpace the release rate for hours, memory use climbs until Node-RED slows down or crashes. You can cap queues globally with the nodeMessageBufferMaxLength setting in settings.js, but the better fix is to choose dropping for telemetry.
Example: Throttle a Fast Sensor Before Publishing
Simulate a noisy sensor and throttle it to one message every two seconds before republishing on a summary topic. Replace 3e5b with your own random string to keep the topics unique on the public broker.
[
{"id":"tabdl","type":"tab","label":"Delay demo"},
{"id":"brkdl","type":"mqtt-broker","name":"ConnectMQ public","broker":"broker.connectmq.com","port":"1883","clientid":"nr-delay-3e5b","autoConnect":true,"usetls":false,"protocolVersion":"4","keepalive":"60","cleansession":true},
{"id":"tick","type":"inject","z":"tabdl","name":"every 200 ms","props":[{"p":"payload","v":"","vt":"date"}],"repeat":"0.2","once":true,"onceDelay":"1","x":130,"y":80,"wires":[["sim"]]},
{"id":"sim","type":"function","z":"tabdl","name":"simulate vibration","func":"msg.topic = 'connectmq/demo/3e5b/press1/vibration';\nmsg.payload = { mm_s: Number((2 + Math.random() * 3).toFixed(2)), ts: msg.payload };\nreturn msg;","outputs":1,"x":330,"y":80,"wires":[["rate"]]},
{"id":"rate","type":"delay","z":"tabdl","name":"1 msg / 2 s, drop","pauseType":"rate","timeout":"5","timeoutUnits":"seconds","rate":"1","nbRateUnits":"2","rateUnits":"second","randomFirst":"1","randomLast":"5","randomUnits":"seconds","drop":true,"allowrate":false,"outputs":1,"x":540,"y":80,"wires":[["pub","dbgdl"]]},
{"id":"pub","type":"mqtt out","z":"tabdl","name":"publish","topic":"","qos":"0","retain":"false","broker":"brkdl","x":730,"y":60,"wires":[]},
{"id":"dbgdl","type":"debug","z":"tabdl","name":"released","active":true,"complete":"payload","x":740,"y":110,"wires":[]}
]
Five messages a second go in; one message every two seconds comes out, always a fresh reading. Watch the result from a terminal:
mosquitto_sub -h broker.connectmq.com -p 1883 -i demo-sub-3e5b \
-t "connectmq/demo/3e5b/#" -v
Without the delay node, this flow would publish five messages a second from one client, already half the public broker's per-client limit. Add a second sensor and you would be at the limit.
Per-Topic Rate Limiting for Many Sensors
When a single mqtt in node subscribes with a wildcard such as connectmq/demo/3e5b/+/telemetry, a plain rate limit treats all topics as one stream. A chatty sensor would then crowd out a quiet one. Switch the delay node to Rate limit → For each msg.topic.
In this mode the node keeps only the most recent message for each topic and releases them at the configured rate, cycling through topics. Every sensor gets its turn, and only its latest value is sent. That is exactly what a dashboard or a database writer wants. Make sure msg.topic is set correctly; if every message has the same topic, per-topic mode behaves like a single queue of one.
Control the Queue at Runtime
A delay node in queueing mode listens for special properties on incoming messages:
| Property | Effect |
|---|---|
msg.reset |
Clears the queue without sending anything |
msg.flush |
Sends queued messages immediately; a number sends that many |
msg.rate |
In rate limit mode with the "allow msg.rate to override" option, changes the rate in milliseconds between messages |
msg.delay |
In override mode, sets this message's delay in milliseconds |
msg.reset is useful when a machine stops: queued readings from before the stop are no longer meaningful. msg.flush helps when a connection comes back and you want to release buffered commands at once. Wire an inject node with the property set to true to try them.
Debouncing Alerts with a Delay
Rate limits also cure alert storms. Place a rate-limited delay node set to one message per 10 minutes with drop intermediate messages before an email or chat notification node. The first alert goes out at once; repeats within the window are discarded. For per-device alerts, set msg.topic to the device ID and use per-topic mode, so one device cannot suppress another's alarm. If you prefer to keep this logic in code, the cooldown example in our Node-RED subflows guide does the same thing per topic.
Common Mistakes Checklist
- Queueing telemetry. Use drop or per-topic mode when only the latest value matters.
- Rate limiting after the expensive step. Put the delay node before database writes, HTTP calls or heavy function nodes, not after.
- Missing
msg.topic. Per-topic mode needs a meaningful topic on every message. - Confusing delay with rate limit. Delay mode shifts every message; it does not reduce the message count.
- Throttling at the wrong layer. If devices publish far faster than anyone needs, fix the firmware sample rate instead of discarding data in Node-RED.
- Ignoring broker limits. Know your broker's message rate and size limits and design below them.
For transformations before or after throttling, see the Node-RED function node guide, and for the basics of wiring MQTT in Node-RED, the Node-RED MQTT tutorial. The delay node's options are also documented in the built-in help and the Node-RED core nodes documentation.
Publish Throttled Data to ConnectMQ
Once your flow publishes at a sensible rate, move it to a private broker. ConnectMQ is a hosted MQTT broker with TLS on port 8883, MQTT 5 message expiry and per-plan quotas that protect every tenant from floods. The free Serverless plan supports up to 25 connections and 256 KB messages, and paid Serverless plans add QoS 2 and shared subscriptions when you scale. Create your broker at app.connectmq.com with no credit card, then switch the broker node to TLS with your generated credentials. To compare deployment models, read our guide to the cloud MQTT broker.
Frequently Asked Questions
What is the difference between delay and rate limit in the Node-RED delay node?
Delay mode holds each message for a time but passes every message through. Rate limit mode controls how many messages leave per interval and can queue or drop the extra ones.
How do I rate limit each MQTT topic separately in Node-RED?
Set the delay node's action to Rate limit and choose "For each msg.topic". The node keeps the latest message per topic and releases topics in turn at the configured rate.
How do I clear a delay node's queue?
Send a message with msg.reset set to any value. The queue is emptied without sending the queued messages.
Can the delay node cause memory problems?
Yes, if it queues messages faster than it releases them for long periods. Use drop or per-topic mode for telemetry, or limit queue size with nodeMessageBufferMaxLength in settings.js.



