Back to Blog
Node.jsProcessEnvironmentBackend

Node.js Process Module Guide

Master the Node.js process module for environment, arguments, and process control.

B
Bootspring Team
Engineering
October 11, 2018
6 min read

The process module provides information about and control over the current Node.js process. Here's how to use it.

Environment Variables#

1// Access environment variables 2const nodeEnv = process.env.NODE_ENV; 3const port = process.env.PORT || 3000; 4const apiKey = process.env.API_KEY; 5 6// Check environment 7const isDev = process.env.NODE_ENV === 'development'; 8const isProd = process.env.NODE_ENV === 'production'; 9 10// Set environment variable (runtime only) 11process.env.MY_VAR = 'value'; 12 13// All environment variables 14console.log(process.env); 15 16// Common patterns 17const config = { 18 port: parseInt(process.env.PORT, 10) || 3000, 19 dbUrl: process.env.DATABASE_URL, 20 debug: process.env.DEBUG === 'true', 21 logLevel: process.env.LOG_LEVEL || 'info', 22};

Command Line Arguments#

1// Raw arguments 2console.log(process.argv); 3// ['/path/to/node', '/path/to/script.js', 'arg1', 'arg2'] 4 5// Skip node and script path 6const args = process.argv.slice(2); 7 8// Simple argument parsing 9const flags = {}; 10const positional = []; 11 12for (const arg of args) { 13 if (arg.startsWith('--')) { 14 const [key, value] = arg.slice(2).split('='); 15 flags[key] = value ?? true; 16 } else if (arg.startsWith('-')) { 17 flags[arg.slice(1)] = true; 18 } else { 19 positional.push(arg); 20 } 21} 22 23// Usage: node script.js --verbose --port=3000 file.txt 24// flags: { verbose: true, port: '3000' } 25// positional: ['file.txt']

Process Information#

1// Process ID 2console.log('PID:', process.pid); 3console.log('Parent PID:', process.ppid); 4 5// Node.js version 6console.log('Node Version:', process.version); 7console.log('V8 Version:', process.versions.v8); 8 9// Platform info 10console.log('Platform:', process.platform); // 'darwin', 'linux', 'win32' 11console.log('Architecture:', process.arch); // 'x64', 'arm64' 12 13// Current working directory 14console.log('CWD:', process.cwd()); 15 16// Change directory 17process.chdir('/path/to/dir'); 18 19// Script location 20console.log('Script:', process.argv[1]); 21console.log('Execution path:', process.execPath);

Memory Usage#

1// Memory usage in bytes 2const memory = process.memoryUsage(); 3 4console.log({ 5 rss: `${Math.round(memory.rss / 1024 / 1024)} MB`, // Resident Set Size 6 heapTotal: `${Math.round(memory.heapTotal / 1024 / 1024)} MB`, 7 heapUsed: `${Math.round(memory.heapUsed / 1024 / 1024)} MB`, 8 external: `${Math.round(memory.external / 1024 / 1024)} MB`, 9}); 10 11// Format helper 12function formatMemory() { 13 const mem = process.memoryUsage(); 14 const format = (bytes) => `${(bytes / 1024 / 1024).toFixed(2)} MB`; 15 16 return { 17 rss: format(mem.rss), 18 heapTotal: format(mem.heapTotal), 19 heapUsed: format(mem.heapUsed), 20 }; 21} 22 23// Memory monitoring 24setInterval(() => { 25 console.log('Memory:', formatMemory()); 26}, 5000);

Process Exit#

1// Exit with success 2process.exit(0); 3 4// Exit with error 5process.exit(1); 6 7// Exit code without exiting 8process.exitCode = 1; 9 10// Clean exit 11function gracefulShutdown() { 12 console.log('Shutting down...'); 13 14 server.close(() => { 15 db.disconnect(() => { 16 process.exit(0); 17 }); 18 }); 19 20 // Force exit after timeout 21 setTimeout(() => { 22 process.exit(1); 23 }, 10000); 24} 25 26// Exit event (synchronous only) 27process.on('exit', (code) => { 28 console.log('Exit code:', code); 29 // Cannot do async work here! 30}); 31 32// Before exit (can do async) 33process.on('beforeExit', async (code) => { 34 await cleanup(); 35 console.log('Cleaned up'); 36});

Signal Handling#

1// SIGINT (Ctrl+C) 2process.on('SIGINT', () => { 3 console.log('Received SIGINT'); 4 gracefulShutdown(); 5}); 6 7// SIGTERM (kill command) 8process.on('SIGTERM', () => { 9 console.log('Received SIGTERM'); 10 gracefulShutdown(); 11}); 12 13// SIGHUP (terminal closed) 14process.on('SIGHUP', () => { 15 console.log('Received SIGHUP'); 16 reloadConfig(); 17}); 18 19// Windows doesn't support all signals 20if (process.platform !== 'win32') { 21 process.on('SIGUSR1', () => { 22 console.log('Received SIGUSR1'); 23 }); 24} 25 26// Remove signal handler 27function handler() { /* ... */ } 28process.on('SIGINT', handler); 29process.off('SIGINT', handler);

Error Handling#

1// Uncaught exceptions 2process.on('uncaughtException', (error, origin) => { 3 console.error('Uncaught Exception:', error); 4 console.error('Origin:', origin); 5 6 // Log error 7 fs.writeSync( 8 process.stderr.fd, 9 `Uncaught Exception: ${error}\n` 10 ); 11 12 process.exit(1); 13}); 14 15// Unhandled promise rejections 16process.on('unhandledRejection', (reason, promise) => { 17 console.error('Unhandled Rejection:', reason); 18 19 // In Node.js 15+, unhandled rejections crash by default 20}); 21 22// Rejection handled later 23process.on('rejectionHandled', (promise) => { 24 console.log('Rejection handled'); 25}); 26 27// Warning events 28process.on('warning', (warning) => { 29 console.warn('Warning:', warning.name, warning.message); 30}); 31 32// Emit custom warning 33process.emitWarning('Something deprecated', 'DeprecationWarning');

Standard I/O#

1// Standard streams 2process.stdin // Readable stream 3process.stdout // Writable stream 4process.stderr // Writable stream 5 6// Write to stdout 7process.stdout.write('Hello\n'); 8 9// Write to stderr 10process.stderr.write('Error message\n'); 11 12// Read from stdin 13process.stdin.setEncoding('utf8'); 14process.stdin.on('data', (data) => { 15 console.log('Input:', data.trim()); 16}); 17 18// Pipe stdin to stdout 19process.stdin.pipe(process.stdout); 20 21// Check if TTY (terminal) 22if (process.stdout.isTTY) { 23 console.log('Running in terminal'); 24 console.log('Columns:', process.stdout.columns); 25 console.log('Rows:', process.stdout.rows); 26}

Timing Functions#

1// High-resolution time 2const start = process.hrtime.bigint(); 3// ... do work 4const end = process.hrtime.bigint(); 5console.log(`Took ${end - start} nanoseconds`); 6 7// Legacy hrtime 8const [seconds, nanoseconds] = process.hrtime(); 9 10// Diff from previous 11const startTime = process.hrtime(); 12// ... do work 13const [secs, nanos] = process.hrtime(startTime); 14console.log(`Took ${secs}s ${nanos}ns`); 15 16// CPU usage 17const startUsage = process.cpuUsage(); 18// ... do work 19const diff = process.cpuUsage(startUsage); 20console.log('CPU:', diff); // { user, system } in microseconds 21 22// Process uptime 23console.log('Uptime:', process.uptime(), 'seconds');

Next Tick#

1// Schedule callback before I/O 2process.nextTick(() => { 3 console.log('Next tick'); 4}); 5 6console.log('Current tick'); 7 8// Output: 9// Current tick 10// Next tick 11 12// Compare with setImmediate 13process.nextTick(() => console.log('nextTick')); 14setImmediate(() => console.log('setImmediate')); 15console.log('sync'); 16 17// Output: 18// sync 19// nextTick 20// setImmediate 21 22// Use case: Emit events after constructor 23class MyEmitter extends EventEmitter { 24 constructor() { 25 super(); 26 process.nextTick(() => { 27 this.emit('ready'); 28 }); 29 } 30} 31 32const emitter = new MyEmitter(); 33emitter.on('ready', () => console.log('Ready!'));

Resource Limits#

1// Resource usage (Unix only) 2const usage = process.resourceUsage(); 3console.log(usage); 4 5// Limits 6process.setUncaughtExceptionCaptureCallback((err) => { 7 console.error('Captured:', err); 8}); 9 10// Max listeners warning threshold 11process.setMaxListeners(20); 12 13// Environment size 14process.env.LARGE_VAR = 'x'.repeat(1000000); 15// Be careful with large env vars

Debugging#

1// Debug port 2console.log('Debug port:', process.debugPort); 3 4// Active handles and requests 5console.log('Active handles:', process._getActiveHandles().length); 6console.log('Active requests:', process._getActiveRequests().length); 7 8// Force garbage collection (requires --expose-gc flag) 9if (global.gc) { 10 global.gc(); 11} 12 13// Report (requires Node.js 12+) 14const report = process.report; 15if (report) { 16 console.log(report.getReport()); 17}

Best Practices#

Environment: ✓ Validate required env vars at startup ✓ Use defaults for optional vars ✓ Don't store secrets in code ✓ Parse/validate env var types Signals: ✓ Handle SIGTERM for graceful shutdown ✓ Handle SIGINT for dev convenience ✓ Set exit codes appropriately ✓ Clean up resources on exit Errors: ✓ Log uncaught exceptions ✓ Handle unhandled rejections ✓ Exit after fatal errors ✓ Monitor warnings Avoid: ✗ Swallowing uncaught exceptions ✗ Ignoring unhandled rejections ✗ Synchronous work in exit handlers ✗ Modifying process.env in production

Conclusion#

The process module is essential for Node.js applications. Use it for environment configuration, command-line argument parsing, graceful shutdown handling, and error management. Always handle SIGTERM and SIGINT for proper shutdown, log uncaught errors, and set appropriate exit codes. The process module provides valuable debugging information about memory usage, timing, and system resources.

Share this article

Help spread the word about Bootspring