os.totalmem()
Returns the total amount of system memory in bytes as an integer.
os.totalmem()- Added in Node.js v0.3.3
Return value
integerThe total amount of system memory in bytes, as an integer.
os.totalmem() reports the machine's installed physical memory in bytes. It is a constant for the lifetime of the process on real hardware, which makes it the denominator in almost every memory-percentage calculation.
When to reach for it
Use it to size caches and buffers relative to the box rather than hard-coding a megabyte figure that is wrong on both a laptop and a 512 GB server: Math.min(512 * 1024 * 1024, os.totalmem() * 0.1) is a common shape. It is also the right number for a diagnostics banner, and for pairing with os.freemem() to express memory pressure as a percentage.
What trips people up
Like os.cpus(), it reports the host, not your limits. In a container with a 256 MB memory cgroup on a 64 GB host it still returns roughly 64 GB, so a cache sized from it will be OOM-killed. It is also unrelated to V8's heap ceiling — Node will not use this much memory just because it exists; that is governed by --max-old-space-size. Divide by 1024 ** 3 for gibibytes, and note that vendors advertise GB as 1000 ** 3, so a "16 GB" machine prints as about 14.9 GiB unless you use the decimal divisor.
Example
When to use it
- Size an in-memory cache as a fraction of the machine's RAM
- Print installed memory in a startup diagnostics line
- Compute a memory-pressure percentage together with os.freemem()
Frequently asked questions
Does os.totalmem() respect Docker memory limits?
No. It reports the host machine's installed RAM even when the container has a much smaller memory cgroup, so a 256 MB container on a 64 GB host still sees 64 GB. Read /sys/fs/cgroup/memory.max (cgroup v2) or memory.limit_in_bytes (v1) when you need the real ceiling.
How do I convert os.totalmem() to GB?
Divide by 1024 ** 3 for gibibytes, which is what most system tools display, or by 1000 ** 3 for the decimal gigabytes hardware vendors advertise. The two differ by about 7%, so a machine sold as 16 GB shows as 14.9 GiB under the binary divisor.
Why does Node crash with out of memory long before os.totalmem() is reached?
Because V8 caps the JavaScript heap independently of physical RAM, at roughly 4 GB on 64-bit by default. Raise it with --max-old-space-size=<MB> if you genuinely need a bigger heap; os.totalmem() only tells you what the machine has, not what V8 will let you allocate.
More examples
Size a cache as a fraction of RAM
The floor and ceiling are what make this usable: without them, 10% of a 512 GB server is a 51 GB cache and 10% of a 512 MB box is too small to be useful. The last line confirms the floor kicks in when the fraction would produce a trivially small budget.
const os = require('node:os');
const MB = 1024 ** 2;
function cacheBudget({ fraction = 0.1, floor = 32 * MB, ceiling = 512 * MB } = {}) {
const share = os.totalmem() * fraction;
return Math.round(Math.min(ceiling, Math.max(floor, share)));
}
console.log('total MB:', Math.round(os.totalmem() / MB));
console.log('10% budget MB:', Math.round(cacheBudget() / MB));
console.log('1% budget MB:', Math.round(cacheBudget({ fraction: 0.01 }) / MB));
console.log('floor respected:', cacheBudget({ fraction: 0.0001 }) === 32 * MB);Format bytes for humans, binary and decimal
The same byte count prints as two different numbers: the binary form is what free and Task Manager show, while the decimal form matches how the machine was advertised. A 16 GiB machine reads as 17.18 GB in decimal, which is the source of most "my numbers do not match" bug reports.
const os = require('node:os');
function format(bytes, base) {
const units = base === 1024
? ['B', 'KiB', 'MiB', 'GiB', 'TiB']
: ['B', 'kB', 'MB', 'GB', 'TB'];
let i = 0;
let n = bytes;
while (n >= base && i < units.length - 1) { n /= base; i++; }
return `${n.toFixed(2)} ${units[i]}`;
}
const total = os.totalmem();
console.log('raw bytes:', total);
console.log('binary (1024):', format(total, 1024));
console.log('decimal (1000):', format(total, 1000));Prefer the container limit when one exists
Where a cgroup v2 limit is readable, the two printed figures differ and the smaller one is the number your process is actually held to. Outside a container the read fails, the catch swallows it, and the function falls back to os.totalmem() with both lines matching.
const os = require('node:os');
const fs = require('node:fs');
function memoryLimit() {
// cgroup v2 exposes the limit here; 'max' means unlimited.
try {
const raw = fs.readFileSync('/sys/fs/cgroup/memory.max', 'utf8').trim();
if (raw !== 'max') return { bytes: Number(raw), source: 'cgroup' };
} catch {
// Not Linux, no cgroup v2, or the path is unreadable.
}
return { bytes: os.totalmem(), source: 'os.totalmem()' };
}
const { bytes, source } = memoryLimit();
console.log('limit source:', source);
console.log('limit (MB):', Math.round(bytes / 1024 ** 2));
console.log('host total (MB):', Math.round(os.totalmem() / 1024 ** 2));
Discussion