jsguides

os module

The os module is a core Node.js module that provides methods for retrieving information about the operating system, CPU, memory, and network interfaces. It is useful for building system monitoring tools, configuring application behavior based on the platform, and gathering diagnostic information.

Syntax

const os = require('os');

No arguments are required. The module is loaded synchronously. Once imported, you can query the underlying system through a set of method calls that return platform identifiers, memory statistics, CPU details, and network configuration.

Platform Information

os.platform()

Returns the operating system platform.

console.log(os.platform());
// 'linux', 'darwin', 'win32'

The return value from platform() is a compact identifier — 'linux', 'darwin', or 'win32' — designed for programmatic comparison in conditional statements. If you need the human-readable name for display or logging, use type() instead.

os.type()

Returns the operating system name.

console.log(os.type());
// 'Linux', 'Darwin', 'Windows_NT'

The values from type() are capitalized proper names, which makes them suitable for user-facing messages. For the underlying kernel version number — useful when checking whether a specific feature or fix is available — call release().

os.release()

Returns the operating system release version.

console.log(os.release());
// '5.4.0-1087-aws'

The release string follows platform conventions: on Linux it is the kernel version, on macOS it is the Darwin kernel version, and on Windows it is the NT version number. Pair it with arch() when you need the full platform fingerprint — for example, when selecting a prebuilt binary or reporting diagnostics.

os.arch()

Returns the CPU architecture.

console.log(os.arch());
// 'x64', 'arm64', 'arm'

The architecture value tells you whether you are on a 64-bit Intel machine or an ARM-based system like a Raspberry Pi or Apple Silicon Mac. Once you know what kind of hardware you are running on, the next practical question is usually how much of that hardware is available right now.

System Memory

os.totalmem()

Returns the total amount of system memory in bytes.

const total = os.totalmem();
console.log(`Total memory: ${(total / 1024 / 1024 / 1024).toFixed(2)} GB`);
// Total memory: 16.00 GB

totalmem() gives you the installed capacity, but that number rarely changes during a process lifetime. The value you typically want to monitor is how much of that memory is still unallocated, which is what freemem() reports.

os.freemem()

Returns the amount of free system memory in bytes.

const free = os.freemem();
console.log(`Free memory: ${(free / 1024 / 1024 / 1024).toFixed(2)} GB`);
// Free memory: 8.50 GB

A raw byte count is precise but hard to interpret at a glance. Dashboards and monitoring scripts usually express free memory as a percentage of total, which makes it easier to set thresholds and compare across machines with different capacities.

os.freemem() percentage

Calculate available memory as a percentage.

const total = os.totalmem();
const free = os.freemem();
const percentFree = (free / total * 100).toFixed(1);
console.log(`Free: ${percentFree}%`);
// Free: 53.1%

Memory is one side of the resource picture. The other is CPU, where the number of cores and the current load shape how many concurrent tasks the machine can handle.

CPU Information

os.cpus()

Returns an array of objects containing information about each CPU core.

console.log(os.cpus().length);
// 8

const cpus = os.cpus();
cpus.forEach((cpu, index) => {
  console.log(`Core ${index}: ${cpu.model}`);
  console.log(`  Speed: ${cpu.speed} MHz`);
});
// Core 0: Intel(R) Xeon(R) Platinum...
//   Speed: 2500 MHz

Each entry in the cpus() array describes one logical core with its model name, speed in MHz, and a times object that breaks down CPU time into user, system, idle, and other categories. For a higher-level picture of how busy the machine is right now, loadavg() condenses the system load into three numbers.

os.loadavg()

Returns an array containing the 1, 5, and 15 minute load averages.

console.log(os.loadavg());
// [0.5, 0.3, 0.2]

Note: This is only meaningful on Unix-like systems. On Windows, it returns [0, 0, 0].

The load average tells you how contended the CPUs are, but it does not tell you about the network. For that, you need to inspect the machine’s interfaces, their assigned addresses, and their state.

Network Interfaces

os.networkInterfaces()

Returns an object containing network interfaces.

const interfaces = os.networkInterfaces();
console.log(Object.keys(interfaces));
// ['lo', 'eth0', 'docker0']

const eth0 = interfaces.eth0;
if (eth0) {
  eth0.forEach(info => {
    console.log(`${info.family}: ${info.address}`);
  });
}
// IPv4: 10.0.1.100
// IPv6: fe80::1

Network interfaces map names like eth0 or lo to arrays of address objects, each with an IP, netmask, MAC address, and address family. After you know the machine’s hardware and network configuration, you often need to know who is running the process — for log directories, config paths, or permission checks.

User Info

os.userInfo()

Returns information about the current user.

const user = os.userInfo();
console.log(user);
// {
//   uid: 1000,
//   gid: 1000,
//   username: 'node',
//   homedir: '/home/node',
//   shell: '/bin/bash'
// }

The homedir field from userInfo() is the most commonly used piece — it gives you the user’s home directory, which is where CLI tools typically store config files, caches, and logs. Combine it with path.join() to build platform-appropriate file paths without hardcoding separators.

Common Patterns

Build system-specific paths

const path = require('path');
const homedir = os.homedir();
const configDir = path.join(homedir, '.myapp');

When os fits best

The os module is most useful when your code needs to adapt to the machine it is running on. A CLI might write logs into a user-specific directory, a monitoring tool might report CPU and memory details, and a server might change its defaults depending on whether it is running on Linux or Windows. Those are all good fits because the answer comes from the host system itself rather than application state.

It is less useful for business logic that should behave the same everywhere. If you only need the current user name or a path separator, the platform details may not matter much. In those cases, keep the dependency narrow and read only the property you actually need so the code stays easier to test and mock.

Portability Notes

Some os methods behave differently across platforms. os.loadavg() is meaningful on Unix-like systems but returns zeros on Windows, so code that displays it should explain that limitation. Network interface names also vary by machine, which means hardcoding eth0 can break on laptops, containers, or cloud instances. Treat the returned structure as data to inspect, not as a promise that specific keys always exist.

The module is synchronous and cheap to call, but you still should not poll it in a tight loop unless you need live metrics. For dashboards, sample on a timer and cache the last reading. For startup decisions, read the values once and configure the app before it begins serving requests.

Monitor system resources

setInterval(() => {
  const free = os.freemem();
  const total = os.totalmem();
  const used = total - free;
  console.log(`Memory: ${(used / total * 100).toFixed(1)}%`);
}, 5000);

A periodic memory check like the one above works well for health dashboards and process monitors. For configuration decisions that happen once at startup, you can also read the platform name and use it to set environment-specific defaults for your application.

Detect development vs production environment

const isProduction = os.platform() === 'win32' 
  ? process.env.NODE_ENV === 'production'
  : process.env.NODE_ENV === 'production';

See Also