Only show guides for your app
Read process.memoryUsage(), recognise the handful of patterns that leak memory in bots and web apps, and find the culprit before an out-of-memory kill finds it for you.
A memory leak is code that keeps holding on to data it no longer needs, so your app's memory only ever grows. On a Falix server that ends one way: the container is killed when it exceeds its RAM (exit code 137), and your bot or site drops offline. This guide shows you how to measure Node's memory, spot the patterns that cause leaks, and narrow down the one in your code.
| At a glance | |
|---|---|
| You need | A Falix server running the Node.js application |
| Plan | Any — free shares 2.5 GB RAM, so leaks bite sooner; premium gives you your plan's RAM |
| Time | Twenty minutes |
Memory that rises and then levels off is normal — Node grows its heap to a working size and stays there. A leak is memory that rises and never comes back down across hours of steady use. Watch the RAM card on the Console page: a slow, sawtooth-free climb toward your limit over hours is the tell. A one-time jump that plateaus is just your app warming up.
process.memoryUsage()Node hands you the numbers directly. Add this anywhere and check the console:
setInterval(() => {
const m = process.memoryUsage();
const mb = (n) => (n / 1024 / 1024).toFixed(1);
console.log(`rss ${mb(m.rss)}MB | heapUsed ${mb(m.heapUsed)}MB | external ${mb(m.external)}MB`);
}, 60_000);
process.memoryUsage() returns five numbers, all in bytes:
| Field | What it measures | Watch it when |
|---|---|---|
rss |
Total resident memory the process holds — the number Falix compares to your limit | Always; this is what triggers the OOM kill |
heapUsed |
JavaScript objects currently alive | Your own data structures leaking |
heapTotal |
Heap V8 has reserved (≥ heapUsed) | Rarely on its own |
external |
Memory used by C++ objects bound to JS (buffers, some native modules) | Native-module or buffer leaks |
arrayBuffers |
The slice of external that is ArrayBuffer/Buffer data |
Streaming/file/image work |
🎯 Good to know:
rssis the one Falix enforces. Ifrssclimbs steadily whileheapUsedstays flat, the growth is outside the JS heap — look at buffers, streams, or a native module, not your objects.
Almost every Node leak is one of these. Each is something that keeps growing without a matching cleanup:
| Pattern | The leak | The fix |
|---|---|---|
| Unbounded cache/Map | You cache.set(key, value) forever and never delete old entries |
Cap it (evict oldest) or give entries a TTL |
| Listeners added in a loop | emitter.on(...) / client.on(...) inside a handler that runs repeatedly, never removed |
Register listeners once at startup, or pair every on with an off/removeListener |
| Global arrays that only grow | Pushing to a module-level logs = [] / history = [] and never trimming |
Keep the last N, or write to a database/file instead |
| Timers holding references | setInterval closures that capture large objects and are never clearInterval'd |
Clear timers you no longer need |
| Per-request state on a shared object | Storing request/message data on a long-lived singleton | Keep request-scoped data local to the handler |
For a Discord bot the classic version is a Map of per-guild or per-user state that you add to but never prune. For a web app it's a response cache with no size limit. Same shape, same fix: bound it.
⚠️ Heads up: Node warns about one of these for you.
MaxListenersExceededWarning: Possible EventEmitter memory leak detectedin the console almost always means you're adding listeners in a loop. Move the.on(...)call to run once.
You don't have a full profiler on a panel host, but you rarely need one:
memoryUsage() on a timer (the snippet above). Let it run and watch whether heapUsed or external is the one climbing — that tells you which kind of thing is leaking.myMap.size / myArray.length next to the memory line. A number that only ever goes up is your leak.A bounded cache is the single most common fix — here's the shape:
const cache = new Map();
const MAX = 500;
function remember(key, value) {
if (cache.size >= MAX) {
cache.delete(cache.keys().next().value); // drop the oldest
}
cache.set(key, value);
}
--max-old-space-size realityYou may read that raising Node's heap limit fixes memory crashes. Two honest points for Falix:
node command, which means editing the full startup command — and that's premium-only. The Additional Arguments (NODE_ARGS) variable is appended after your filename, so it reaches your script, not node. Don't expect NODE_ARGS to set node flags.Fix the leak instead of raising the ceiling; it's the only change that actually holds.
external climbing, heap flat — buffers or a native module. Look at file/image/stream code that isn't releasing buffers.For the full toolset (heap snapshots, the --inspect protocol, v8.getHeapStatistics()), the official Node.js diagnostics guide takes it further than a panel host can.