Back to Course
Modules

Exploring Node.js Core Modules

Node.js core modules are built-in modules that come with Node.js installation. They provide essential functionality for file system operations, networking, path manipulation, operating system interactions, and much more. Mastering these modules is the foundation of every Node.js application.

Production Reality: Core modules are the building blocks of every Node.js application. Understanding them thoroughly will make you a more effective developer and help you avoid unnecessary third-party dependencies.

1. fs (File System) Module — Working with Files

The fs module provides an API for interacting with the file system. It has both synchronous and asynchronous methods.

Common fs Methods

MethodDescriptionAsync Version
readFileRead a filefs.promises.readFile
writeFileWrite to a filefs.promises.writeFile
appendFileAppend to a filefs.promises.appendFile
mkdirCreate a directoryfs.promises.mkdir
readdirRead directory contentsfs.promises.readdir
statGet file/directory statsfs.promises.stat
unlinkDelete a filefs.promises.unlink
rmdirDelete a directoryfs.promises.rmdir
existsCheck if file existsfs.promises.access
renameRename a filefs.promises.rename
copyFileCopy a filefs.promises.copyFile
createReadStreamStream file content
createWriteStreamStream write to file

Production Example — Read/Write Files

const fs = require('fs').promises;
const path = require('path');

// ✅ Production-ready: Async/await with error handling
async function readUserData(filePath) {
    try {
        const data = await fs.readFile(filePath, 'utf8');
        return JSON.parse(data);
    } catch (err) {
        if (err.code === 'ENOENT') {
            console.error('File not found:', filePath);
            return null;
        }
        console.error('Error reading file:', err.message);
        throw err;
    }
}

async function writeUserData(filePath, data) {
    try {
        // Ensure directory exists
        const dir = path.dirname(filePath);
        await fs.mkdir(dir, { recursive: true });
        await fs.writeFile(filePath, JSON.stringify(data, null, 2), 'utf8');
        console.log('Data written successfully');
    } catch (err) {
        console.error('Error writing file:', err.message);
        throw err;
    }
}

// Usage
const userData = await readUserData('./data/users.json');
await writeUserData('./data/users.json', { name: 'John', age: 30 });

Streaming Large Files

const fs = require('fs');
const { pipeline } = require('stream');
const { promisify } = require('util');

const pipelineAsync = promisify(pipeline);

// ✅ Production: Stream large files without memory issues
async function copyLargeFile(source, destination) {
    const readStream = fs.createReadStream(source, { highWaterMark: 64 * 1024 });
    const writeStream = fs.createWriteStream(destination);

    // Handle errors
    readStream.on('error', (err) => console.error('Read error:', err));
    writeStream.on('error', (err) => console.error('Write error:', err));

    // Using pipeline for proper backpressure handling
    await pipelineAsync(readStream, writeStream);
    console.log('File copied successfully');
}
Production Warning: Never use synchronous methods (readFileSync, writeFileSync) in request handlers. They block the event loop. Always use the fs.promises API or callback-based async methods.

2. path Module — Cross-Platform Path Handling

The path module provides utilities for working with file and directory paths, automatically handling platform differences (Windows vs. Unix).

MethodDescriptionExample
joinJoin path segmentspath.join('/usr', 'local', 'bin')
resolveResolve an absolute pathpath.resolve('src', 'app.js')
dirnameGet directory namepath.dirname('/usr/local/bin')
basenameGet filenamepath.basename('/usr/local/bin')
extnameGet file extensionpath.extname('file.txt')
parseParse path into objectpath.parse('/usr/local/bin')
relativeGet relative pathpath.relative('/usr', '/usr/local/bin')
isAbsoluteCheck if path is absolutepath.isAbsolute('/usr/local/bin')

Production Examples

const path = require('path');

// ✅ Always use path.join for cross-platform compatibility
const configPath = path.join(__dirname, 'config', 'app.json');

// ✅ Use path.resolve for absolute paths
const absolutePath = path.resolve('node_modules', 'express');

// ✅ Parse a path
const parsed = path.parse('/home/user/project/src/index.js');
// {
//   root: '/',
//   dir: '/home/user/project/src',
//   base: 'index.js',
//   ext: '.js',
//   name: 'index'
// }

// ✅ Get file info
const dir = path.dirname(__filename);
const base = path.basename(__filename);
const ext = path.extname(__filename);

console.log('File:', base); // 'app.js'
console.log('Directory:', dir); // '/home/user/project'
console.log('Extension:', ext); // '.js'

3. http/https Module — Building Web Servers

The http and https modules provide the foundation for building web servers and making HTTP requests.

Production HTTP Server

const http = require('http');
const url = require('url');
const querystring = require('querystring');

const server = http.createServer((req, res) => {
    const parsedUrl = url.parse(req.url, true);
    const pathname = parsedUrl.pathname;

    // Route handling
    if (pathname === '/') {
        res.writeHead(200, { 'Content-Type': 'text/html' });
        res.end('<h1>Hello, World!</h1>');
    } else if (pathname === '/api/users') {
        const users = [{ id: 1, name: 'John' }, { id: 2, name: 'Jane' }];
        res.writeHead(200, { 'Content-Type': 'application/json' });
        res.end(JSON.stringify(users));
    } else {
        res.writeHead(404, { 'Content-Type': 'text/plain' });
        res.end('404 Not Found');
    }
});

// ✅ Production: Handle errors gracefully
server.on('error', (err) => {
    console.error('Server error:', err);
});

server.listen(3000, () => {
    console.log('Server running on http://localhost:3000');
});

Making HTTP Requests

const http = require('http');
const https = require('https');

// ✅ Production: Fetch data from external API
function fetchData(url) {
    return new Promise((resolve, reject) => {
        const client = url.startsWith('https') ? https : http;
        client.get(url, (res) => {
            let data = '';
            res.on('data', (chunk) => data += chunk);
            res.on('end', () => {
                try {
                    resolve(JSON.parse(data));
                } catch (err) {
                    reject(new Error('Invalid JSON response'));
                }
            });
        }).on('error', (err) => {
            reject(err);
        });
    });
}

// Usage
try {
    const data = await fetchData('https://api.example.com/users');
    console.log(data);
} catch (err) {
    console.error('Failed to fetch data:', err.message);
}

4. os Module — Operating System Information

The os module provides information about the operating system, which is useful for monitoring, diagnostics, and system-specific behavior.

MethodDescriptionExample Output
cpusCPU core informationArray of CPU objects
totalmemTotal system memory16777216 (16GB)
freememFree system memory4294967296 (4GB)
platformOS platform'linux', 'darwin', 'win32'
releaseOS release version'5.15.0-67-generic'
hostnameSystem hostname'production-server'
typeOS type'Linux', 'Windows_NT'
uptimeSystem uptime (seconds)86400 (1 day)
loadavgSystem load average[1.5, 0.8, 0.5]

Production Monitoring Example

const os = require('os');

// ✅ Production: System health monitoring
function getSystemInfo() {
    const totalMemGB = (os.totalmem() / 1024 / 1024 / 1024).toFixed(2);
    const freeMemGB = (os.freemem() / 1024 / 1024 / 1024).toFixed(2);
    const usedMemGB = (totalMemGB - freeMemGB).toFixed(2);
    const memUsagePercent = ((1 - os.freemem() / os.totalmem()) * 100).toFixed(2);

    return {
        platform: os.platform(),
        release: os.release(),
        hostname: os.hostname(),
        uptime: `${Math.floor(os.uptime() / 3600)} hours, ${Math.floor((os.uptime() % 3600) / 60)} minutes`,
        cpuCores: os.cpus().length,
        cpuModel: os.cpus()[0]?.model || 'Unknown',
        totalMemory: `${totalMemGB} GB`,
        freeMemory: `${freeMemGB} GB`,
        usedMemory: `${usedMemGB} GB`,
        memoryUsage: `${memUsagePercent}%`,
        loadAverage: os.loadavg().join(', '),
    };
}

// Health check endpoint
app.get('/health', (req, res) => {
    const info = getSystemInfo();
    res.json({
        status: 'healthy',
        timestamp: new Date().toISOString(),
        system: info
    });
});

5. events Module — Event Emitter

The events module implements the Node.js event-driven architecture. It's used by many core modules and is essential for building loosely coupled systems.

Event Emitter Examples

const EventEmitter = require('events');

// ✅ Production: Create a custom event emitter
class OrderService extends EventEmitter {
    createOrder(orderData) {
        // Validate order
        if (!orderData.items || orderData.items.length === 0) {
            this.emit('error', new Error('Order must have at least one item'));
            return;
        }

        // Process order
        this.emit('order.created', orderData);

        // Simulate async processing
        setTimeout(() => {
            this.emit('order.processed', {
                ...orderData,
                status: 'processed',
                processedAt: new Date().toISOString()
            });
        }, 2000);

        return { id: Date.now(), ...orderData };
    }
}

// Usage
const orderService = new OrderService();

// Listen to events
orderService.on('order.created', (order) => {
    console.log('📦 Order created:', order.id);
    // Send confirmation email
});

orderService.on('order.processed', (order) => {
    console.log('✅ Order processed:', order.id);
    // Update inventory
});

orderService.on('error', (err) => {
    console.error('❌ Order error:', err.message);
});

// Create an order
orderService.createOrder({
    items: [{ id: 1, name: 'Item 1' }, { id: 2, name: 'Item 2' }]
});

Best Practices for Event Emitters

  • Always handle 'error' events — unhandled errors crash the process.
  • Limit listeners — use setMaxListeners() to avoid memory leaks.
  • Remove listeners when no longer needed.
  • Use once() for one-time events to avoid memory leaks.
// ✅ Proper event listener management
class Service extends EventEmitter {
    constructor() {
        super();
        this.setMaxListeners(20); // Increase limit

        // Use once for one-time events
        this.once('ready', () => {
            console.log('Service ready');
        });

        // Use off to remove listeners
        this.on('data', (data) => { /* process data */ });
        this.off('data', this._dataHandler);
    }
}

6. crypto Module — Cryptographic Functions

The crypto module provides cryptographic functionality including hashing, encryption, signing, and random number generation.

MethodDescriptionUse Case
createHashCreate a hashPassword hashing, checksums
createHmacHMAC generationAPI authentication
randomBytesGenerate random bytesAPI keys, tokens
createCipherivEncrypt dataData encryption
createDecipherivDecrypt dataData decryption
pbkdf2Password-based key derivationSecure password storage

Production Examples

const crypto = require('crypto');

// ✅ 1. Password hashing (PBKDF2)
async function hashPassword(password) {
    const salt = crypto.randomBytes(32).toString('hex');
    const iterations = 100000;
    const keylen = 64;
    const digest = 'sha512';

    return new Promise((resolve, reject) => {
        crypto.pbkdf2(password, salt, iterations, keylen, digest, (err, derivedKey) => {
            if (err) reject(err);
            resolve({
                hash: derivedKey.toString('hex'),
                salt: salt,
                iterations: iterations
            });
        });
    });
}

async function verifyPassword(password, storedHash, salt) {
    const iterations = 100000;
    const keylen = 64;
    const digest = 'sha512';

    return new Promise((resolve, reject) => {
        crypto.pbkdf2(password, salt, iterations, keylen, digest, (err, derivedKey) => {
            if (err) reject(err);
            resolve(derivedKey.toString('hex') === storedHash);
        });
    });
}

// ✅ 2. Generate secure API key
function generateApiKey() {
    return crypto.randomBytes(32).toString('hex');
}

// ✅ 3. HMAC for API authentication
function generateHmacSignature(payload, secret) {
    const hmac = crypto.createHmac('sha256', secret);
    hmac.update(JSON.stringify(payload));
    return hmac.digest('hex');
}

// ✅ 4. Hash a file for checksum
function hashFile(data) {
    const hash = crypto.createHash('sha256');
    hash.update(data);
    return hash.digest('hex');
}

// Usage
const apiKey = generateApiKey();
console.log('API Key:', apiKey);

const hashed = await hashPassword('securePassword123');
const isValid = await verifyPassword('securePassword123', hashed.hash, hashed.salt);
console.log('Password valid:', isValid);
Production Warning: Never use MD5 or SHA1 for security-critical applications. Use SHA256, SHA512, or bcrypt. Always use PBKDF2 with a high iteration count (100,000+) for password hashing.

7. util Module — Utility Functions

The util module provides various utility functions for debugging, type checking, and promise handling.

Production Examples

const util = require('util');
const fs = require('fs');

// ✅ 1. promisify — Convert callback-based functions to promises
const readFileAsync = util.promisify(fs.readFile);
const writeFileAsync = util.promisify(fs.writeFile);

async function readConfig() {
    try {
        const data = await readFileAsync('./config.json', 'utf8');
        return JSON.parse(data);
    } catch (err) {
        console.error('Failed to read config:', err.message);
        return null;
    }
}

// ✅ 2. types — Type checking
const types = require('util/types');
console.log(types.isDate(new Date())); // true
console.log(types.isRegExp(/test/)); // true

// ✅ 3. inspect — Better object inspection
const obj = {
    name: 'John',
    nested: {
        deep: {
            values: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
        }
    }
};
console.log(util.inspect(obj, { 
    depth: null, 
    colors: true,
    showHidden: true 
}));

// ✅ 4. deprecate — Mark functions as deprecated
const oldApi = util.deprecate(
    () => { console.log('Old API called'); },
    'oldApi() is deprecated. Use newApi() instead.'
);

oldApi(); // Shows deprecation warning

8. url & querystring Modules — URL Handling

The url and querystring modules provide utilities for parsing and manipulating URLs and query strings.

const url = require('url');
const querystring = require('querystring');

// ✅ Parse URLs
const urlString = 'https://api.example.com/users?page=2&limit=10&sort=asc';
const parsedUrl = new URL(urlString);

console.log(parsedUrl.hostname); // 'api.example.com'
console.log(parsedUrl.pathname); // '/users'
console.log(parsedUrl.searchParams.get('page')); // '2'
console.log(parsedUrl.searchParams.get('limit')); // '10'

// ✅ Build URLs
const params = new URLSearchParams({
    page: 3,
    limit: 20,
    sort: 'desc'
});

const newUrl = new URL('https://api.example.com/products');
newUrl.search = params.toString();
console.log(newUrl.toString()); // https://api.example.com/products?page=3&limit=20&sort=desc

// ✅ Parse query string (legacy)
const qs = 'page=2&limit=10&sort=asc';
const parsedQs = querystring.parse(qs);
console.log(parsedQs); // { page: '2', limit: '10', sort: 'asc' }

// ✅ Stringify query string
const stringified = querystring.stringify({ page: 2, limit: 10 });
console.log(stringified); // 'page=2&limit=10'

9. Core Modules Quick Reference

ModuleCommon Use CasesProduction Importance
fsFile reading/writing, logging, config storage🔴 Critical
pathFile path handling, cross-platform compatibility🔴 Critical
http/httpsWeb servers, API clients, external requests🔴 Critical
osSystem monitoring, health checks🟡 Important
eventsEvent-driven architecture, loose coupling🟡 Important
cryptoSecurity, hashing, encryption, authentication🔴 Critical
utilDebugging, promisification, type checking🟢 Nice to have
urlURL parsing, query string handling🟡 Important

10. Production-Ready Checklist

  • ✅ Always use fs.promises — Avoid callback-based methods; use async/await.
  • ✅ Never use synchronous methodsreadFileSync, writeFileSync block the event loop.
  • ✅ Use path.join — For cross-platform compatibility.
  • ✅ Implement streaming — Use streams for large files to avoid memory issues.
  • ✅ Handle errors — Always handle errors in file operations and network requests.
  • ✅ Set max listeners — Use setMaxListeners() for event emitters.
  • ✅ Use crypto.randomBytes — For generating secure tokens and API keys.
  • ✅ Use PBKDF2 — For password hashing with high iteration count.
  • ✅ Monitor system resources — Use os module for health checks.
  • ✅ Promisify callbacks — Use util.promisify for consistent async patterns.
  • ✅ Validate URLs — Always validate and sanitize URLs and query strings.
  • ✅ Remove event listeners — Prevent memory leaks by removing unused listeners.
Production Wisdom: Core modules are the foundation of every Node.js application. Master them thoroughly and you'll be able to build almost anything without heavy third-party dependencies. When choosing between a core module and a third-party package, start with the core module — it's often enough and eliminates unnecessary dependencies.

Ready to master Node.js?

Build scalable, high-performance backend applications with Node.js. Learn from industry experts with hands-on projects.

Explore Course