os.freemem()

Returns the amount of free system memory in bytes as an integer.

Signature
os.freemem()
  • Added in Node.js v0.3.3

Return value

integerThe amount of free system memory in bytes, as an integer.

os.freemem() returns the operating system's count of unallocated physical memory in bytes. Unlike os.totalmem() it changes constantly — two calls a millisecond apart can differ by megabytes.

When to reach for it

Sampling. A health endpoint, a metrics tick, a log line before and after a heavy job, or a back-pressure check that pauses an ingest loop when the machine gets tight. Paired with os.totalmem() it gives a used-memory percentage, which is the form worth graphing.

What trips people up

The big one on Linux: "free" excludes the page cache. The kernel deliberately fills unused RAM with cached file contents and evicts it instantly under pressure, so a perfectly healthy server routinely reports 2% free. That memory is available; it is just not idle. If you alarm on freemem() < threshold you will page someone at 3am about a machine doing exactly what it should. On Linux, MemAvailable in /proc/meminfo is the number you actually want.

It also reports the host, not your container's cgroup limit, and it says nothing about your process — use process.memoryUsage() for that. Because the value moves, never write a test that asserts on it.

Example

Try it yourself
Loading editor…
Press Run to execute the code.

When to use it

  • Expose a memory gauge from a /health or metrics endpoint
  • Pause a bulk ingest loop when free memory drops below a floor
  • Log system memory before and after a large batch job to spot a leak

Frequently asked questions

Why does os.freemem() report so little free memory on Linux?

Because Linux uses spare RAM for the page cache and os.freemem() counts only genuinely unallocated pages. That cached memory is reclaimed instantly when a process needs it, so low "free" is normal and healthy. Read MemAvailable from /proc/meminfo for the number that reflects what is actually obtainable.

Does os.freemem() show memory available to my container?

No, it reports the host machine's free memory and ignores your cgroup limit entirely. Inside a memory-limited container read /sys/fs/cgroup/memory.current against memory.max to see your own usage and headroom.

What is the difference between os.freemem() and process.memoryUsage()?

os.freemem() measures the whole machine's unallocated RAM, while process.memoryUsage() measures your own process — rss, heapTotal, heapUsed, external and arrayBuffers. Use the second one to find a leak in your code; the first only tells you how much room the machine has left.

More examples

A memory gauge for a health endpoint

The output is the shape you would return from /health: absolute megabytes plus a percentage, because the raw byte count means nothing to whoever reads the dashboard. On a Linux host expect the status to look worse than reality, since the page cache counts as used.

Example · javascript
const os = require('node:os');

function memoryHealth() {
  const total = os.totalmem();
  const free = os.freemem();
  const usedPct = (1 - free / total) * 100;
  return {
    totalMB: Math.round(total / 1024 ** 2),
    freeMB: Math.round(free / 1024 ** 2),
    usedPct: Number(usedPct.toFixed(1)),
    status: usedPct > 95 ? 'critical' : usedPct > 85 ? 'warn' : 'ok'
  };
}

console.log(JSON.stringify(memoryHealth(), null, 2));

Back-pressure on a processing loop

The paused count shows how often the loop had to yield; on a machine with headroom it stays 0 and the loop runs straight through. The pattern matters more than the numbers: checking free memory per item lets a bulk job slow down instead of being OOM-killed.

Example · javascript
import os from 'node:os';

const MB = 1024 ** 2;
const FLOOR = 64 * MB;

async function processAll(items) {
  let done = 0;
  let paused = 0;
  for (const item of items) {
    if (os.freemem() < FLOOR) {
      paused++;
      global.gc?.();
      await new Promise((r) => setTimeout(r, 10));
    }
    done += item.length;
  }
  return { done, paused };
}

const items = Array.from({ length: 500 }, (_, i) => 'row-' + i);
console.log(await processAll(items));
console.log('floor MB:', FLOOR / MB);
console.log('free MB now:', Math.round(os.freemem() / MB));

Prefer MemAvailable on Linux

On Linux the two megabyte figures usually diverge sharply, because MemAvailable includes reclaimable page cache while os.freemem() does not. The MemAvailable figure is the one to alert on; os.freemem() will look alarmingly low on any machine that has been reading files.

Example · javascript
const os = require('node:os');
const fs = require('node:fs');

function available() {
  try {
    const meminfo = fs.readFileSync('/proc/meminfo', 'utf8');
    const match = /^MemAvailable:\s+(\d+) kB$/m.exec(meminfo);
    if (match) return { bytes: Number(match[1]) * 1024, source: 'MemAvailable' };
  } catch {
    // Not Linux, or /proc is not mounted.
  }
  return { bytes: os.freemem(), source: 'os.freemem()' };
}

const { bytes, source } = available();
console.log('source:', source);
console.log('available MB:', Math.round(bytes / 1024 ** 2));
console.log('os.freemem() MB:', Math.round(os.freemem() / 1024 ** 2));

Discussion

  • Be the first to comment on this lesson.