Weird issue with node-red closing after a while on android

Hi all, got a bit of an odd issue with node-red. I've got a set up with an old kiosk-type android device that I've set up to work as a digital switch for a fan. Using termux to run node-red at boot, it serves a simple webpage that a browser on the same device (as well as a second device not running node-red) connects to and uses websockets to synchronize. It seems to run fine for about 1-2 weeks, then I'll come into work the next day and both browsers will be saying they can't connect to the web page being served.
Using ssh/adb to connect to the device hosting node-red and using tools like top shows that node-red simply isn't running anymore. I couldn't find any helpful logs from nodejs or anything, so I went and modified the logger function in node-red's settings.js to just dump any log messages to a file that I could look at later on. After waiting a couple weeks for it to crash again (and sifting through about 400MB of logs which was about as much fun as it sounds), it seemed to just suddenly stop with no indication of what was going on. The final few lines are just logs about memory usage:

2026-05-29T10:09:09.074Z: {"level":99,"event":"runtime.memory.rss","value":47058944,"timestamp":1780049349074}
2026-05-29T10:09:09.075Z: {"level":99,"event":"runtime.memory.heapTotal","value":48660480,"timestamp":1780049349075}
2026-05-29T10:09:09.076Z: {"level":99,"event":"runtime.memory.heapUsed","value":40551820,"timestamp":1780049349076}
2026-05-29T10:09:24.075Z: {"level":99,"event":"runtime.memory.rss","value":47083520,"timestamp":1780049364075}
2026-05-29T10:09:24.076Z: {"level":99,"event":"runtime.memory.heapTotal","value":48660480,"timestamp":1780049364076}
2026-05-29T10:09:24.077Z: {"level":99,"event":"runtime.memory.heapUsed","value":40264408,"timestamp":1780049364077}
2026-05-29T10:09:39.075Z: {"level":99,"event":"runtime.memory.rss","value":47087616,"timestamp":1780049379075}
2026-05-29T10:09:39.076Z: {"level":99,"event":"runtime.memory.heapTotal","value":48660480,"timestamp":1780049379076}
2026-05-29T10:09:39.076Z: {"level":99,"event":"runtime.memory.heapUsed","value":40398380,"timestamp":1780049379076}
2026-05-29T10:09:54.079Z: {"level":99,"event":"runtime.memory.rss","value":46895104,"timestamp":1780049394079}
2026-05-29T10:09:54.080Z: {"level":99,"event":"runtime.memory.heapTotal","value":48660480,"timestamp":1780049394080}
2026-05-29T10:09:54.081Z: {"level":99,"event":"runtime.memory.heapUsed","value":40529048,"timestamp":1780049394081}
2026-05-29T10:10:09.077Z: {"level":99,"event":"runtime.memory.rss","value":46899200,"timestamp":1780049409077}
2026-05-29T10:10:09.078Z: {"level":99,"event":"runtime.memory.heapTotal","value":48660480,"timestamp":1780049409078}
2026-05-29T10:10:09.078Z: {"level":99,"event":"runtime.memory.heapUsed","value":40659524,"timestamp":1780049409078}

Though one important thing to note is that the memory use is steadily going up. It goes down intermittently (probably the GC) but over time it's definitely higher. I eventually realized that I had a debug node set up to record the control data being sent to the mocked fan speed controller (It hasn't been properly hooked up due to the whole "can't run for more than 2 weeks at a time" thing).
I have removed this but I don't really want to wait another 2 weeks to see if there's any other possible causes. Another thing to note is that although the memory is constantly going up, the final log messages indicated that I still had another 8MB of heap space and it was only going up by a couple MB per hour on average.
What's weirder still is that I couldn't find any other evidence of low memory issues on the device. No LMKD messages in logcat or kernel messages relating to it in dmseg. Long term memory monitoring isn't really practical due to me only being in the office 8 hours a day and having better things to do than watch top's output for 2 weeks straight.
I have considered disk space as an issue, but du says I still have a bit over 1.3GB of space in my data directory, even with the file logging generating nearly 400MB of logs between crashes.
My boot script isn't anything special:

#!/data/data/com.termux/files/usr/bin/sh

termux-wake-lock
/data/data/com.termux/files/usr/bin/node /data/data/com.termux/files/usr/bin/node-red > /data/data/com.termux/files/home/nodered-boot-log 2>&1

and the data dumped to the boot-log file is pretty much useless:

2 Jun 10:47:34 - [info] 

Welcome to Node-RED
===================

1780363054948 undefined
2 Jun 10:47:35 - [info] Node-RED version: v4.1.1
1780363055162 undefined
2 Jun 10:47:35 - [info] Node.js  version: v22.20.0
1780363055171 undefined
2 Jun 10:47:35 - [info] Linux 3.10.65 arm LE
1780363055179 undefined
null
null
null
null
2 Jun 10:47:45 - [info] Loading palette nodes
1780363065440 undefined
1780363071371 runtime.memory.rss
1780363071375 runtime.memory.heapTotal
1780363071377 runtime.memory.heapUsed
null
null
null
null
2 Jun 10:48:04 - [info] Dashboard version 3.6.6 started at /ui
1780363084025 undefined
2 Jun 10:48:07 - [info] Settings file  : /data/data/com.termux/files/home/.node-red/settings.js
1780363087048 undefined
2 Jun 10:48:07 - [info] Context store  : 'default' [module=memory]
1780363087056 undefined
2 Jun 10:48:07 - [info] User directory : /data/data/com.termux/files/home/.node-red
1780363087067 undefined
2 Jun 10:48:07 - [warn] Projects disabled : editorTheme.projects.enabled=false
1780363087072 undefined
2 Jun 10:48:07 - [info] Flows file     : /data/data/com.termux/files/home/.node-red/flows.json
1780363087098 undefined
1780363087131 runtime.memory.rss
1780363087133 runtime.memory.heapTotal
1780363087134 runtime.memory.heapUsed
null
null
null
null
null
null
null
null
null
2 Jun 10:48:07 - [warn] 

---------------------------------------------------------------------
Your flow credentials file is encrypted using a system-generated key.

If the system-generated key is lost for any reason, your credentials
file will not be recoverable, you will have to delete it and re-enter
your credentials.

You should set your own key using the 'credentialSecret' option in
your settings file. Node-RED will then re-encrypt your credentials
file using your chosen key the next time you deploy a change.
---------------------------------------------------------------------

1780363087308 undefined
2 Jun 10:48:07 - [warn] Encrypted credentials not found
1780363087317 undefined
2 Jun 10:48:07 - [info] Server now running at http://127.0.0.1:1880/
1780363087513 undefined
null
null
null
2 Jun 10:48:07 - [info] Starting flows
1780363087545 undefined
2 Jun 10:48:08 - [info] Started flows
1780363088299 undefined
null
null
1780363088801 node.http in.send
1780363088809 node.function.receive
1780363088835 node.function.send
1780363088837 node.function.done
1780363088839 node.function.duration
1780363088842 node.http response.receive
1780363088873 node.http in.response.time.millis
1780363088874 node.http in.response.content-length.bytes
1780363088882 node.http response.done
null
null
null
null
null
null
null
null
null

And then just that block of "node.*" and nulls repeated for another 40k-ish lines

I hope that's enough info provided and I know it's a bit of a long shot, especially considering it'll be a couple weeks before I can find out if anything works, but it's been bugging me for months. Really appreciate any ideas anyone has for this. Nodejs version is v22.20.0, node-red is v4.1.1 and the device is running android 7.1.1.

It isn't that your device is running out of memory, node.js is running out of enough heap to be able to move stuff around and to GC.

One thing to check would be that you don't have any nodes in your flows that have more than 1 wire on an output port if that node produces large messages. e.g. if you are using http-in, it contains a massive amount of data including circular references. Though Node-RED is pretty good at filtering that out when it needs to, you might still be creating deep copies of large data.

Also check for any possible logic loops of course.

You might also want to add a periodic heap check and report that out somewhere so that you can monitor memory usage over time without having to wait 2 weeks.

Ah yeah that makes more sense, though still strange there's no logs or anything I can find from Node complaining about low heap. As for the nodes, the setup is extremely simple:


The payloads being sent over websockets are tiny, pretty much either { "keepalive": 123456 } or { "speed": 1 } (with either proper timestamps or fan speeds) so I doubt the message complexity is the issue here.
I'm going to assume trying to increase Node's heap limit is a dead end since I only have about 2GB of system memory to work with as is, and it'll only really extend how long it can go without crashing.
As I said earlier, I did have a debugging node hooked up that could constantly build memory use if messages are constantly being fed into it, but the docs didn't mention anything about issues with increasing memory use so I assumed they were being persisted to disk, not left in memory. If you reckon that would be the likely culprit I'll leave it disabled and see if it can last longer this time.

I always think it is best to let node.js figure out the memory allocations. In earlier days, it was common to need to tweak things, especially on constrained memory systems but these days they seem to have things fairly well balanced.

As I say, the only other thing would be to capture the heap regularly and pass it out so that you can monitor it more closely.

Not sure there is much else you can do. Running NR on a mobile has never been a "mainstream" option so there is really very little experience. One thing you might want to consider is whether you really need to have the Editor running. It can be disabled which might free up a bunch of resources.

I'll look into heap monitoring but I'm not confident in the feasibility of it since it's a fairly limited device and I'm not sure what options exist for tracking heap usage over time without getting in the way of the resources node-red already seems to be eating too much of. I'll also look into disabling the editor, but that might get in the way of usability. Anyway, thanks for your input and I'll see how it all goes.

Getting the data is fairly easy. Adding this to the top of settings (outside of the export part) will show the memory stats at startup in the log:

const v8 = require('v8')
const mem = process.memoryUsage()

With some adjustment, you could also run this from a flow. Getting the data out - not sure as I've never used NR on Android but there must be ways. Maybe you could pass the data to another instance of Node-RED? And maybe from there to Telegram or dumped to a web page?