Note these are demos to show functionality not the actual way to code
I've come up with a variable rate flow emulator using a function node in conjunction with the delay node set to variable delay dependant on msg.delay
This is so people can try it out and examine/discuss variable rate limiting behaviour
Version1
Code for the function node (copy and pasted from JS generated by Blocky)
[{"id":"a29de14a.f8621","type":"function","z":"71db5e1b.7cbed","name":"Rate Limit","func":"var rate, lastTime;\n\n\nrate = (msg['rate']);\nif (context.get('lastTime')) {\n lastTime = (context.get('lastTime'));\n} else {\n lastTime = new Date().getTime() - 1000000;\n}\nif (rate <= new Date().getTime() - lastTime) {\n context.set('lastTime', new Date().getTime());\n msg['delay'] = 0;\n} else {\n context.set('lastTime', (rate + lastTime));\n msg['delay'] = (rate - (new Date().getTime() - lastTime));\n}\nreturn msg;","outputs":1,"noerr":0,"x":640,"y":640,"wires":[["e888583a.0563b8"]]},{"id":"48c9ceba.5a6b1","type":"inject","z":"71db5e1b.7cbed","name":"","topic":"","payload":"3000","payloadType":"num","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":190,"y":640,"wires":[["28fb0f44.245bb"]]},{"id":"28fb0f44.245bb","type":"change","z":"71db5e1b.7cbed","name":"","rules":[{"t":"set","p":"rate","pt":"msg","to":"payload","tot":"msg"}],"action":"","property":"","from":"","to":"","reg":false,"x":370,"y":640,"wires":[["a29de14a.f8621"]]},{"id":"dc85db79.91cf48","type":"inject","z":"71db5e1b.7cbed","name":"","topic":"","payload":"6000","payloadType":"num","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":190,"y":680,"wires":[["28fb0f44.245bb"]]},{"id":"e888583a.0563b8","type":"delay","z":"71db5e1b.7cbed","name":"","pauseType":"delayv","timeout":"5","timeoutUnits":"seconds","rate":"1","nbRateUnits":"1","rateUnits":"second","randomFirst":"1","randomLast":"5","randomUnits":"seconds","drop":false,"x":820,"y":640,"wires":[["c9b891fb.a0587"]]},{"id":"c9b891fb.a0587","type":"debug","z":"71db5e1b.7cbed","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","x":1010,"y":640,"wires":[]}]
Best played with rather than reading description but here it is anyway
1st message gets passed straight thru with no delay
If a message arrives after the last one has passed thru the delay node - it gets sent on with no delay as well.
If a message arrives before previous rate limit delay period has passed, then the message is delayed the appropriate amount of time so it matches.
This approach means that the rate flow of any messages in the queue is honoured when they enter the queue and not changed in retrospect
Version 2 (needs node-red-contrib-queue-gate)
This shows a demo that sends 8 messages thru it and that lets you vary the flow rate so that the flow rate is applied to the next message released from the q-gate buffer which means better dynamic control of the rate
[{"id":"f7ad7e0c.1ce4e","type":"debug","z":"d0817fc5.e088c","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","targetType":"msg","x":1150,"y":400,"wires":[]},{"id":"96a20a4c.c88258","type":"inject","z":"d0817fc5.e088c","name":"","topic":"","payload":"","payloadType":"date","repeat":"1","crontab":"","once":true,"onceDelay":0.1,"x":170,"y":440,"wires":[["e891be0.76c214"]]},{"id":"e891be0.76c214","type":"q-gate","z":"d0817fc5.e088c","name":"Source Gate","controlTopic":"control","defaultState":"queueing","openCmd":"open","closeCmd":"close","toggleCmd":"toggle","queueCmd":"queue","defaultCmd":"default","triggerCmd":"trigger","flushCmd":"flush","resetCmd":"reset","maxQueueLength":"8","keepNewest":false,"qToggle":false,"persist":false,"x":350,"y":440,"wires":[["f0502eaf.fe599"]]},{"id":"8bcca828.441e98","type":"inject","z":"d0817fc5.e088c","name":"","topic":"control","payload":"flush","payloadType":"str","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":170,"y":480,"wires":[["e891be0.76c214"]]},{"id":"acc5aa53.53f0a8","type":"inject","z":"d0817fc5.e088c","name":"","topic":"","payload":"3000","payloadType":"num","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":350,"y":520,"wires":[["658cf04.5ff061"]]},{"id":"45f57cc6.b2e4b4","type":"inject","z":"d0817fc5.e088c","name":"","topic":"","payload":"6000","payloadType":"num","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":350,"y":560,"wires":[["658cf04.5ff061"]]},{"id":"cae57c47.e0d73","type":"change","z":"d0817fc5.e088c","name":"","rules":[{"t":"set","p":"rate","pt":"flow","to":"payload","tot":"msg"}],"action":"","property":"","from":"","to":"","reg":false,"x":690,"y":520,"wires":[[]]},{"id":"f0502eaf.fe599","type":"delay","z":"d0817fc5.e088c","name":"Needed for demo","pauseType":"rate","timeout":"5","timeoutUnits":"seconds","rate":"100","nbRateUnits":"1","rateUnits":"second","randomFirst":"1","randomLast":"5","randomUnits":"seconds","drop":false,"x":650,"y":440,"wires":[["42359b0c.6d46a4"]]},{"id":"4fcfdd33.0c3fa4","type":"q-gate","z":"d0817fc5.e088c","name":"","controlTopic":"control","defaultState":"queueing","openCmd":"open","closeCmd":"close","toggleCmd":"toggle","queueCmd":"queue","defaultCmd":"default","triggerCmd":"trigger","flushCmd":"flush","resetCmd":"reset","maxQueueLength":"0","keepNewest":false,"qToggle":false,"persist":false,"x":930,"y":460,"wires":[["af5422d5.ddd82"]]},{"id":"af5422d5.ddd82","type":"function","z":"d0817fc5.e088c","name":"","func":"\nreturn msg;","outputs":1,"noerr":0,"x":995,"y":400,"wires":[["f7ad7e0c.1ce4e","e5e46da4.85801"]],"icon":"node-red/arrow-in.svg","l":false},{"id":"448679f1.7d5a98","type":"inject","z":"d0817fc5.e088c","name":"","topic":"control","payload":"trigger","payloadType":"str","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":170,"y":520,"wires":[["e891be0.76c214"]]},{"id":"42359b0c.6d46a4","type":"switch","z":"d0817fc5.e088c","name":"","property":"timerRunning","propertyType":"flow","rules":[{"t":"false"},{"t":"else"}],"checkall":"true","repair":false,"outputs":2,"x":810,"y":440,"wires":[["af5422d5.ddd82"],["4fcfdd33.0c3fa4"]]},{"id":"e7fbd260.b6274","type":"inject","z":"d0817fc5.e088c","name":"","topic":"","payload":"","payloadType":"date","repeat":"","crontab":"","once":true,"onceDelay":0.1,"x":895,"y":580,"wires":[["9390f30d.f5ce7"]],"l":false},{"id":"9390f30d.f5ce7","type":"change","z":"d0817fc5.e088c","name":"","rules":[{"t":"set","p":"timerRunning","pt":"flow","to":"false","tot":"bool"},{"t":"set","p":"topic","pt":"msg","to":"control","tot":"str"},{"t":"set","p":"payload","pt":"msg","to":"reset","tot":"str"}],"action":"","property":"","from":"","to":"","reg":false,"x":935,"y":580,"wires":[["4fcfdd33.0c3fa4"]],"l":false},{"id":"658cf04.5ff061","type":"ui_slider","z":"d0817fc5.e088c","name":"","label":"Rate Slider","tooltip":"","group":"7301eab1.cc8794","order":0,"width":0,"height":0,"passthru":true,"outs":"all","topic":"","min":"1000","max":"10000","step":"1000","x":510,"y":520,"wires":[["cae57c47.e0d73","199b0f79.75b8e1"]]},{"id":"199b0f79.75b8e1","type":"ui_text","z":"d0817fc5.e088c","group":"7301eab1.cc8794","order":1,"width":0,"height":0,"name":"","label":"Milliseconds","format":"{{msg.payload}}","layout":"row-left","x":690,"y":560,"wires":[]},{"id":"e5e46da4.85801","type":"change","z":"d0817fc5.e088c","name":"","rules":[{"t":"set","p":"timerRunning","pt":"flow","to":"true","tot":"bool"},{"t":"set","p":"delay","pt":"msg","to":"rate","tot":"flow"}],"action":"","property":"","from":"","to":"","reg":false,"x":1055,"y":460,"wires":[["1c241624.23bf6a"]],"l":false},{"id":"1c241624.23bf6a","type":"delay","z":"d0817fc5.e088c","name":"","pauseType":"delayv","timeout":"5","timeoutUnits":"seconds","rate":"1","nbRateUnits":"1","rateUnits":"second","randomFirst":"1","randomLast":"5","randomUnits":"seconds","drop":false,"x":1140,"y":460,"wires":[["e1db9e30.5557"]]},{"id":"e1db9e30.5557","type":"change","z":"d0817fc5.e088c","name":"","rules":[{"t":"set","p":"topic","pt":"msg","to":"control","tot":"str"},{"t":"set","p":"payload","pt":"msg","to":"trigger","tot":"str"},{"t":"set","p":"timerRunning","pt":"flow","to":"false","tot":"bool"}],"action":"","property":"","from":"","to":"","reg":false,"x":1235,"y":460,"wires":[["4fcfdd33.0c3fa4"]],"l":false},{"id":"3cdd8356.c5224c","type":"comment","z":"d0817fc5.e088c","name":"Test Message Stream - press control:flush to start","info":"","x":240,"y":400,"wires":[]},{"id":"782f4a2b.c16174","type":"inject","z":"d0817fc5.e088c","name":"","topic":"","payload":"9000","payloadType":"num","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":350,"y":600,"wires":[["658cf04.5ff061"]]},{"id":"7301eab1.cc8794","type":"ui_group","z":"","name":"Rate Group","tab":"f13a38e4.830558","disp":true,"width":"6","collapse":false},{"id":"f13a38e4.830558","type":"ui_tab","z":"","name":"Rate Tab","icon":"dashboard","disabled":false,"hidden":false}]