Node.js Interview Questions Your Guide to Success

Node.js, a powerful JavaScript runtime, is crucial for building scalable server-side applications, making it an essential skill for backend developers and DevOps engineers. Stark.ai offers a curated collection of Node.js interview questions, real-world scenarios, and expert guidance to help you excel in your next technical interview.

Back

nodejs

    • What is Node.js and what are its key features?

      Node.js is an open-source, cross-platform JavaScript runtime environment that executes JavaScript code outside of a...

    • Explain the Node.js architecture and its core components.

      Node.js architecture consists of several key components: 1) V8 Engine: Google's open-source JavaScript engine that...

    • What is the difference between JavaScript in Node.js and in browsers?

      Key differences include: 1) Global object: 'window' in browsers vs 'global' in Node.js, 2) DOM/BOM APIs only...

    • How does Node.js handle concurrent requests?

      Node.js handles concurrent requests through: 1) Event Loop: Single-threaded loop that processes async operations, 2)...

    • What is the role of libuv in Node.js?

      libuv is a multi-platform support library that handles: 1) Asynchronous I/O operations, 2) Thread pool management,...

    • Explain the concept of process and threads in Node.js.

      In Node.js: 1) Process: Instance of a program in execution with its own memory space, 2) Main Thread: Single thread...

    • What are Node.js core modules and how do they differ from external modules?

      Core modules are built-in modules that come with Node.js installation: 1) No installation required (http, fs, path),...

    • How does Node.js implement the CommonJS module system?

      CommonJS implementation in Node.js includes: 1) require() function for module loading, 2) module.exports for...

    • What is the purpose of the process object in Node.js?

      The process object provides information and control over the Node.js process: 1) Environment variables...

    • How does garbage collection work in Node.js?

      Node.js uses V8's garbage collection with two main phases: 1) Scavenge: Fast but partial collection for young...

    • What are the different ways to handle errors in Node.js?

      Error handling in Node.js includes: 1) Try-catch blocks for synchronous code, 2) Error events for EventEmitter, 3)...

    • Explain the role of V8 Engine in Node.js.

      V8 Engine in Node.js: 1) Compiles JavaScript to machine code, 2) Manages memory allocation, 3) Handles garbage...

    • What is Node.js REPL and how is it useful?

      REPL (Read-Eval-Print-Loop) provides an interactive shell for Node.js: 1) Testing code snippets, 2) Debugging, 3)...

    • How does Node.js support ES modules?

      ES modules support in Node.js includes: 1) .mjs extension for ES module files, 2) 'type': 'module' in package.json,...

    • What are Buffer and ArrayBuffer in Node.js?

      Buffers handle binary data in Node.js: 1) Buffer: Node.js specific for binary data, 2) ArrayBuffer: JavaScript...

    • How does clustering work in Node.js?

      Clustering enables running multiple Node.js processes: 1) Master process creates worker processes, 2) Workers share...

    • What are the key differences between Node.js LTS and Current versions?

      Key differences include: 1) LTS (Long Term Support): Stable, production-ready, 30-month support cycle, 2) Current:...

    • How does Node.js handle child processes?

      Child processes in Node.js: 1) spawn(): Streams for large data, 2) exec(): Buffers for completion, 3) fork(): IPC...

    • What is the purpose of process.nextTick() and setImmediate()?

      Timing functions in Node.js: 1) process.nextTick(): Executes callback before next event loop iteration, 2)...

    • What is the Event Loop in Node.js and how does it work?

      The Event Loop is the mechanism that allows Node.js to perform non-blocking I/O operations despite JavaScript being...

    • Explain the difference between Promises, async/await, and callbacks in Node.js.

      Different asynchronous patterns in Node.js serve different purposes: 1) Callbacks: Traditional pattern with...

    • What is the microtask queue and how does it relate to the event loop?

      The microtask queue handles high-priority tasks like Promise callbacks and process.nextTick. Characteristics: 1)...

    • How do you handle errors in asynchronous operations?

      Error handling in async operations can be done through multiple patterns: 1) Callbacks: Use error-first pattern....

    • What is the purpose of the EventEmitter class in Node.js?

      EventEmitter implements the Observer pattern for event-driven programming. Features: 1) Register event listeners, 2)...

    • How does Node.js handle CPU-intensive tasks without blocking the event loop?

      Node.js provides several strategies for CPU-intensive tasks: 1) Worker Threads: Parallel execution of CPU tasks....

    • What are the best practices for handling Promise chains?

      Best practices for Promise chains include: 1) Always return values in .then(), 2) Use single catch at the end, 3)...

    • How do you implement custom async iterators in Node.js?

      Custom async iterators can be implemented using Symbol.asyncIterator: Example: class AsyncRange { constructor(start,...

    • What is the difference between parallel and concurrent execution in Node.js?

      Key differences: 1) Parallel: Multiple tasks execute simultaneously (Worker Threads, Child Processes), 2)...

    • How do you implement async error handling patterns?

      Async error handling patterns include: 1) Try-catch with async/await. Example: async function handle() { try { await...

    • How does Node.js handle timer functions internally?

      Node.js timer functions work through: 1) Timer phase in event loop, 2) Min heap data structure for efficient timer...

    • What are async hooks in Node.js and how are they used?

      Async hooks track lifecycle of async operations: 1) init: Resource creation, 2) before: Callback execution start, 3)...

    • How do you implement custom promises in Node.js?

      Custom promises can be implemented using the Promise constructor: Example: function customPromise(value) { return...

    • What are the different phases of Promise execution?

      Promise execution phases include: 1) Pending: Initial state, 2) Fulfilled: Successful completion, 3) Rejected: Error...

    • How do you implement throttling and debouncing in Node.js?

      Throttling and debouncing control function execution frequency: 1) Throttle: Limit execution rate. Example: function...

    • How do you handle race conditions in async operations?

      Race conditions can be handled through: 1) Promise.race() for first completion, 2) Mutex implementation for...

    • Explain the concept of event loop starvation and how to prevent it.

      Event loop starvation occurs when CPU-intensive tasks block the event loop from processing other events. Prevention...

    • How do you implement cancellable promises in Node.js?

      Cancellable promises can be implemented using: 1) AbortController for fetch operations, 2) Custom cancel tokens, 3)...

    • What are the patterns for handling concurrent database operations?

      Patterns for concurrent database operations include: 1) Connection pooling, 2) Transaction management, 3) Batch...

    • How do you implement retry mechanisms for async operations?

      Retry mechanisms can be implemented using: 1) Exponential backoff, 2) Maximum retry limits, 3) Retry delay...

    • What are the strategies for handling memory leaks in async operations?

      Memory leak prevention strategies include: 1) Proper event listener cleanup, 2) Closing resources (files,...

    • How do you implement async iterators for custom data sources?

      Async iterators can be implemented using Symbol.asyncIterator: Example: class DataSource { constructor(data) {...

    • What are the patterns for implementing rate limiting in async operations?

      Rate limiting patterns include: 1) Token bucket algorithm, 2) Sliding window, 3) Fixed window counting, 4) Leaky...

    • How do you handle timeouts in async operations?

      Timeout handling includes: 1) Promise race with timeout promise, 2) AbortController integration, 3) Cleanup on...

    • How do you implement async dependency injection?

      Async dependency injection patterns include: 1) Factory functions, 2) Async constructors, 3) Dependency containers....

    • What are the patterns for handling distributed events in Node.js?

      Distributed event patterns include: 1) Message queues, 2) Pub/sub systems, 3) Event buses, 4) Webhook...

    • How do you implement async middleware patterns?

      Async middleware patterns include: 1) Pipeline pattern, 2) Chain of responsibility, 3) Composition pattern. Example:...

    • What are the strategies for handling backpressure in async streams?

      Backpressure handling strategies include: 1) Implementing pause/resume mechanisms, 2) Buffer size limits, 3)...

    • How do you implement async error boundaries?

      Async error boundaries can be implemented using: 1) Higher-order functions, 2) Class wrappers, 3) Decorator...

    • What are the different module systems in Node.js?

      Node.js supports multiple module systems: 1) CommonJS (require/exports): Traditional Node.js module system. Example:...

    • How does Node.js resolve module dependencies?

      Node.js module resolution follows these steps: 1) Core modules (like 'fs'), 2) Local modules with relative paths...

    • What is package.json and what are its key components?

      package.json is a project manifest file containing: 1) Basic info (name, version, description), 2) Dependencies...

    • How do you manage dependencies using npm?

      NPM dependency management includes: 1) Installing packages: npm install package-name, 2) Saving dependencies: --save...

    • What are peer dependencies and when should you use them?

      Peer dependencies specify packages that must be installed by the consuming application. Used when: 1) Creating...

    • How do you handle circular dependencies in Node.js?

      Circular dependencies can be handled through: 1) Restructuring code to avoid cycles, 2) Using dependency injection,...

    • What is npm workspaces and how do you use it?

      NPM workspaces enable managing multiple packages in a single repository: 1) Define workspaces in root package.json,...

    • How do you optimize module loading performance?

      Module loading optimization techniques: 1) Use module caching effectively, 2) Implement lazy loading, 3) Bundle...

    • What are the different ways to version Node.js packages?

      Package versioning methods include: 1) Semantic Versioning (MAJOR.MINOR.PATCH), 2) Version ranges (^, ~, *, x), 3)...

    • How do you publish and maintain npm packages?

      Package publishing process: 1) Prepare package.json (name, version, files), 2) Create npm account, 3) npm login, 4)...

    • What is the role of package-lock.json?

      package-lock.json ensures consistent installs across environments by: 1) Locking exact versions of dependencies, 2)...

    • How do you handle native modules in Node.js?

      Native modules management includes: 1) node-gyp for compilation, 2) Binary distribution using prebuilt packages, 3)...

    • What are the security best practices for dependency management?

      Security practices include: 1) Regular security audits (npm audit), 2) Version pinning for critical dependencies, 3)...

    • How do you implement module mocking in tests?

      Module mocking approaches: 1) Jest mock functions, 2) Proxyquire for dependency injection, 3) Manual mocking....

    • What are the different module scoping patterns in Node.js?

      Module scoping patterns include: 1) IIFE (Immediately Invoked Function Expression), 2) Revealing Module Pattern, 3)...

    • How do you manage environment-specific dependencies?

      Environment-specific dependency management: 1) Development vs production dependencies, 2) Optional dependencies, 3)...

What is Node.js and what are its key features?

Node.js is an open-source, cross-platform JavaScript runtime environment that executes JavaScript code outside of a web browser. Key features include: 1) Event-driven and non-blocking I/O model, 2) Single-threaded event loop with asynchronous programming, 3) NPM (Node Package Manager) for package management, 4) Built-in modules for file system operations, networking, etc., 5) Cross-platform support, 6) Active community and extensive ecosystem.

Explain the Node.js architecture and its core components.

Node.js architecture consists of several key components: 1) V8 Engine: Google's open-source JavaScript engine that compiles JS to native machine code, 2) libuv: Handles async operations, event loop, and thread pool, 3) Core Modules: Built-in modules like http, fs, path, 4) Node Standard Library: JavaScript implementation of core functionality, 5) Node Package Manager (NPM): Package management system. This architecture enables efficient, non-blocking operations and cross-platform compatibility.

What is the difference between JavaScript in Node.js and in browsers?

Key differences include: 1) Global object: 'window' in browsers vs 'global' in Node.js, 2) DOM/BOM APIs only available in browsers, 3) File system access available in Node.js but not browsers, 4) Module systems: CommonJS in Node.js vs ES Modules in modern browsers, 5) Threading: Web Workers in browsers vs Worker Threads in Node.js, 6) Different security models and constraints. Understanding these differences is crucial for Node.js development.

How does Node.js handle concurrent requests?

Node.js handles concurrent requests through: 1) Event Loop: Single-threaded loop that processes async operations, 2) Thread Pool: Handles CPU-intensive tasks and I/O operations, 3) Non-blocking I/O: Async operations don't block the main thread, 4) Callback Queue: Manages completed async operations, 5) Worker Threads: For CPU-intensive tasks. Example: server.on('request', (req, res) => { // Async operation db.query('SELECT * FROM users', (err, results) => { res.end(JSON.stringify(results)); }); });

What is the role of libuv in Node.js?

libuv is a multi-platform support library that handles: 1) Asynchronous I/O operations, 2) Thread pool management, 3) Event loop implementation, 4) Network operations, 5) File system operations, 6) Inter-process communication. It abstracts underlying OS differences and provides a consistent async I/O interface across platforms. Example: const fs = require('fs'); fs.readFile('file.txt', (err, data) => {}); // handled by libuv behind the scenes

Explain the concept of process and threads in Node.js.

In Node.js: 1) Process: Instance of a program in execution with its own memory space, 2) Main Thread: Single thread running event loop, 3) Worker Threads: Additional threads for CPU-intensive tasks, 4) Thread Pool: Managed by libuv for async operations. Example using worker threads: const { Worker } = require('worker_threads'); const worker = new Worker('./worker.js'); worker.postMessage('start'); worker.on('message', (result) => console.log(result));

What are Node.js core modules and how do they differ from external modules?

Core modules are built-in modules that come with Node.js installation: 1) No installation required (http, fs, path), 2) Higher performance as they're preloaded, 3) Fundamental functionality implementation, 4) Written in C++ for performance. External modules are third-party modules installed via NPM. Example: const http = require('http'); // core module vs const express = require('express'); // external module

How does Node.js implement the CommonJS module system?

CommonJS implementation in Node.js includes: 1) require() function for module loading, 2) module.exports for exposing functionality, 3) Module caching for performance, 4) Module resolution algorithm. Example: // math.js module.exports = { add: (a, b) => a + b }; // main.js const math = require('./math'); console.log(math.add(2, 3)); // Module loading is synchronous and cached

What is the purpose of the process object in Node.js?

The process object provides information and control over the Node.js process: 1) Environment variables (process.env), 2) Command line arguments (process.argv), 3) Process control (process.exit()), 4) Event handling for process lifecycle, 5) CPU and memory usage information. Example: process.on('uncaughtException', (err) => { console.error('Uncaught Exception:', err); process.exit(1); });

How does garbage collection work in Node.js?

Node.js uses V8's garbage collection with two main phases: 1) Scavenge: Fast but partial collection for young objects, 2) Mark-Sweep: Complete collection for old objects. Features include: 1) Generational collection, 2) Incremental marking, 3) Concurrent sweeping, 4) Memory optimization flags. Example of manual GC trigger (not recommended): global.gc(); // requires --expose-gc flag

What are the different ways to handle errors in Node.js?

Error handling in Node.js includes: 1) Try-catch blocks for synchronous code, 2) Error events for EventEmitter, 3) Error-first callbacks for async operations, 4) Promise rejection handling, 5) Global error handlers. Example: process.on('unhandledRejection', (reason, promise) => { console.log('Unhandled Rejection at:', promise, 'reason:', reason); }); try { throw new Error('Sync Error'); } catch (err) { console.error(err); }

Explain the role of V8 Engine in Node.js.

V8 Engine in Node.js: 1) Compiles JavaScript to machine code, 2) Manages memory allocation, 3) Handles garbage collection, 4) Provides data types and objects, 5) Optimizes code execution. Features include: JIT compilation, inline caching, hidden classes for optimization. Example of V8 flags: node --v8-options --optimize_for_size --max_old_space_size=1024 app.js

What is Node.js REPL and how is it useful?

REPL (Read-Eval-Print-Loop) provides an interactive shell for Node.js: 1) Testing code snippets, 2) Debugging, 3) Experimenting with Node.js features, 4) Quick prototyping. Features include: Auto-completion, Multi-line editing, Command history. Example: node // enters REPL > const sum = (a, b) => a + b; > sum(2, 3) // 5

How does Node.js support ES modules?

ES modules support in Node.js includes: 1) .mjs extension for ES module files, 2) 'type': 'module' in package.json, 3) Import/export syntax, 4) Dynamic imports, 5) Module resolution rules. Example: // file.mjs export const hello = 'world'; import { hello } from './file.mjs'; // Dynamic import: const module = await import('./module.mjs');

What are Buffer and ArrayBuffer in Node.js?

Buffers handle binary data in Node.js: 1) Buffer: Node.js specific for binary data, 2) ArrayBuffer: JavaScript standard binary data container. Features: Direct memory allocation, Binary data operations, Encoding conversions. Example: const buf = Buffer.from('Hello', 'utf8'); console.log(buf); // <Buffer 48 65 6c 6c 6f> console.log(buf.toString()); // Hello

How does clustering work in Node.js?

Clustering enables running multiple Node.js processes: 1) Master process creates worker processes, 2) Workers share server ports, 3) Load balancing between workers, 4) IPC communication between processes. Example: const cluster = require('cluster'); if (cluster.isMaster) { cluster.fork(); cluster.fork(); } else { require('./server.js'); }

What are the key differences between Node.js LTS and Current versions?

Key differences include: 1) LTS (Long Term Support): Stable, production-ready, 30-month support cycle, 2) Current: Latest features, shorter support cycle, potentially unstable. LTS focuses on stability and security, while Current provides newest features. Release schedule: New major version every 6 months, LTS versions released yearly.

How does Node.js handle child processes?

Child processes in Node.js: 1) spawn(): Streams for large data, 2) exec(): Buffers for completion, 3) fork(): IPC channel for Node.js processes, 4) execFile(): Execute executable files. Example: const { spawn } = require('child_process'); const ls = spawn('ls', ['-l']); ls.stdout.on('data', (data) => console.log(data.toString()));

What is the purpose of process.nextTick() and setImmediate()?

Timing functions in Node.js: 1) process.nextTick(): Executes callback before next event loop iteration, 2) setImmediate(): Executes in check phase of event loop. Key differences: nextTick has higher priority and runs before I/O events. Example: process.nextTick(() => console.log('nextTick')); setImmediate(() => console.log('setImmediate'));

What is the Event Loop in Node.js and how does it work?

The Event Loop is the mechanism that allows Node.js to perform non-blocking I/O operations despite JavaScript being single-threaded. It works in phases: 1) Timers (setTimeout, setInterval), 2) Pending callbacks (I/O callbacks), 3) Idle, prepare (internal use), 4) Poll (new I/O events), 5) Check (setImmediate), 6) Close callbacks. Each phase has a FIFO queue of callbacks to execute. Example: console.log('1'); setTimeout(() => console.log('2'), 0); Promise.resolve().then(() => console.log('3')); console.log('4'); // Output: 1, 4, 3, 2

Explain the difference between Promises, async/await, and callbacks in Node.js.

Different asynchronous patterns in Node.js serve different purposes: 1) Callbacks: Traditional pattern with error-first callback style. Example: fs.readFile('file.txt', (err, data) => {}). 2) Promises: Chain-able operations with .then() and .catch(). Example: fetch('url').then(res => res.json()). 3) Async/Await: Syntactic sugar over promises for cleaner code. Example: async function getData() { const response = await fetch('url'); return response.json(); }. Async/await provides better error handling and code readability compared to callbacks and raw promises.

What is the microtask queue and how does it relate to the event loop?

The microtask queue handles high-priority tasks like Promise callbacks and process.nextTick. Characteristics: 1) Processes before the next event loop phase, 2) Higher priority than macrotasks (setTimeout, setInterval), 3) Includes Promise callbacks and process.nextTick callbacks. Example: process.nextTick(() => console.log('1')); Promise.resolve().then(() => console.log('2')); setTimeout(() => console.log('3'), 0); // Output: 1, 2, 3

How do you handle errors in asynchronous operations?

Error handling in async operations can be done through multiple patterns: 1) Callbacks: Use error-first pattern. Example: fs.readFile('file.txt', (err, data) => { if (err) handle(err); }). 2) Promises: Use .catch() or try/catch with async/await. Example: async function readFile() { try { const data = await fs.promises.readFile('file.txt'); } catch (err) { handle(err); } }. 3) Event emitters: Use error event handlers. Example: stream.on('error', (err) => handle(err));

What is the purpose of the EventEmitter class in Node.js?

EventEmitter implements the Observer pattern for event-driven programming. Features: 1) Register event listeners, 2) Emit events, 3) Handle events asynchronously, 4) Multiple listeners per event. Example: const EventEmitter = require('events'); class MyEmitter extends EventEmitter {} const myEmitter = new MyEmitter(); myEmitter.on('event', (data) => console.log(data)); myEmitter.emit('event', 'Hello World');

How does Node.js handle CPU-intensive tasks without blocking the event loop?

Node.js provides several strategies for CPU-intensive tasks: 1) Worker Threads: Parallel execution of CPU tasks. Example: const { Worker } = require('worker_threads'); const worker = new Worker('./worker.js'); 2) Child Processes: Separate Node.js processes. Example: const { fork } = require('child_process'); const child = fork('cpu_task.js'); 3) Chunking: Breaking large tasks into smaller ones. Example: function processChunk(data, callback) { setImmediate(() => { /* process chunk */ callback(); }); }

What are the best practices for handling Promise chains?

Best practices for Promise chains include: 1) Always return values in .then(), 2) Use single catch at the end, 3) Avoid nesting promises, 4) Use Promise.all() for parallel operations, 5) Handle rejections properly. Example: fetchUser(id).then(user => { return fetchPosts(user.id); }).then(posts => { return processPosts(posts); }).catch(error => { handleError(error); });

How do you implement custom async iterators in Node.js?

Custom async iterators can be implemented using Symbol.asyncIterator: Example: class AsyncRange { constructor(start, end) { this.start = start; this.end = end; } async *[Symbol.asyncIterator]() { for(let i = this.start; i <= this.end; i++) { await new Promise(resolve => setTimeout(resolve, 1000)); yield i; } } } async function iterate() { for await (const num of new AsyncRange(1, 3)) { console.log(num); } }

What is the difference between parallel and concurrent execution in Node.js?

Key differences: 1) Parallel: Multiple tasks execute simultaneously (Worker Threads, Child Processes), 2) Concurrent: Tasks progress simultaneously but execute on single thread (async/await, Promises). Example of parallel: const { Worker } = require('worker_threads'); const workers = [new Worker('./worker.js'), new Worker('./worker.js')]; Example of concurrent: async function concurrent() { const [result1, result2] = await Promise.all([task1(), task2()]); }

How do you implement async error handling patterns?

Async error handling patterns include: 1) Try-catch with async/await. Example: async function handle() { try { await riskyOperation(); } catch (err) { handleError(err); } } 2) Error boundaries: class ErrorBoundary extends EventEmitter { async execute(fn) { try { return await fn(); } catch (err) { this.emit('error', err); } } } 3) Error-first callbacks: function operation(callback) { doAsync((err, result) => callback(err, result)); }

How does Node.js handle timer functions internally?

Node.js timer functions work through: 1) Timer phase in event loop, 2) Min heap data structure for efficient timer management, 3) Internal scheduling using libuv. Example: const start = Date.now(); setTimeout(() => console.log(Date.now() - start), 1000); // Actual delay might be longer due to event loop phases and CPU load. setTimeout and setInterval are not exact timing mechanisms.

What are async hooks in Node.js and how are they used?

Async hooks track lifecycle of async operations: 1) init: Resource creation, 2) before: Callback execution start, 3) after: Callback completion, 4) destroy: Resource cleanup. Example: const async_hooks = require('async_hooks'); const hook = async_hooks.createHook({ init(asyncId, type) { console.log(`${type}: ${asyncId}`); }, destroy(asyncId) { console.log(`Destroyed: ${asyncId}`); } }).enable();

How do you implement custom promises in Node.js?

Custom promises can be implemented using the Promise constructor: Example: function customPromise(value) { return new Promise((resolve, reject) => { if (value) { setTimeout(() => resolve(value), 1000); } else { reject(new Error('Invalid value')); } }); } class AsyncOperation { static async execute() { return new Promise((resolve, reject) => { // Async operation logic }); } }

What are the different phases of Promise execution?

Promise execution phases include: 1) Pending: Initial state, 2) Fulfilled: Successful completion, 3) Rejected: Error state. Methods: .then() for fulfillment, .catch() for rejection, .finally() for cleanup. Example: new Promise((resolve, reject) => { doAsync() }).then(result => { // Fulfilled }).catch(error => { // Rejected }).finally(() => { // Cleanup });

How do you implement throttling and debouncing in Node.js?

Throttling and debouncing control function execution frequency: 1) Throttle: Limit execution rate. Example: function throttle(fn, delay) { let last = 0; return function(...args) { const now = Date.now(); if (now - last >= delay) { last = now; return fn.apply(this, args); } }; } 2) Debounce: Delay execution until pause. Example: function debounce(fn, delay) { let timeoutId; return function(...args) { clearTimeout(timeoutId); timeoutId = setTimeout(() => fn.apply(this, args), delay); }; }

How do you handle race conditions in async operations?

Race conditions can be handled through: 1) Promise.race() for first completion, 2) Mutex implementation for synchronization, 3) Atomic operations, 4) Proper state management. Example: class Mutex { constructor() { this.locked = false; this.queue = []; } async acquire() { return new Promise(resolve => { if (!this.locked) { this.locked = true; resolve(); } else { this.queue.push(resolve); } }); } release() { if (this.queue.length > 0) { const next = this.queue.shift(); next(); } else { this.locked = false; } } }

Explain the concept of event loop starvation and how to prevent it.

Event loop starvation occurs when CPU-intensive tasks block the event loop from processing other events. Prevention methods include: 1) Breaking long tasks into smaller chunks using setImmediate, 2) Using Worker Threads for CPU-intensive work, 3) Implementing proper concurrency controls. Example: function processArray(arr) { let index = 0; function nextChunk() { if (index < arr.length) { let chunk = arr.slice(index, index + 1000); // Process chunk setImmediate(() => nextChunk()); // Schedule next chunk index += 1000; } } nextChunk(); }

How do you implement cancellable promises in Node.js?

Cancellable promises can be implemented using: 1) AbortController for fetch operations, 2) Custom cancel tokens, 3) Wrapper classes with cancel functionality. Example: class CancellablePromise { constructor(executor) { this.abortController = new AbortController(); this.promise = new Promise((resolve, reject) => { executor(resolve, reject, this.abortController.signal); }); } cancel() { this.abortController.abort(); } } const operation = new CancellablePromise((resolve, reject, signal) => { signal.addEventListener('abort', () => reject(new Error('Cancelled'))); });

What are the patterns for handling concurrent database operations?

Patterns for concurrent database operations include: 1) Connection pooling, 2) Transaction management, 3) Batch operations, 4) Rate limiting. Example: class DBOperations { constructor(pool) { this.pool = pool; } async batchInsert(records, batchSize = 1000) { for (let i = 0; i < records.length; i += batchSize) { const batch = records.slice(i, i + batchSize); await Promise.all(batch.map(record => this.insert(record))); } } async transaction(operations) { const client = await this.pool.connect(); try { await client.query('BEGIN'); const results = await Promise.all(operations.map(op => op(client))); await client.query('COMMIT'); return results; } catch (e) { await client.query('ROLLBACK'); throw e; } finally { client.release(); } } }

How do you implement retry mechanisms for async operations?

Retry mechanisms can be implemented using: 1) Exponential backoff, 2) Maximum retry limits, 3) Retry delay calculation, 4) Error type checking. Example: async function retry(operation, maxRetries = 3, delay = 1000) { for (let i = 0; i < maxRetries; i++) { try { return await operation(); } catch (error) { if (i === maxRetries - 1) throw error; const waitTime = delay * Math.pow(2, i); await new Promise(resolve => setTimeout(resolve, waitTime)); } } }

What are the strategies for handling memory leaks in async operations?

Memory leak prevention strategies include: 1) Proper event listener cleanup, 2) Closing resources (files, connections), 3) Monitoring reference counts, 4) Using WeakMap/WeakSet. Example: class ResourceManager { constructor() { this.resources = new WeakMap(); } async useResource(key, resource) { try { this.resources.set(key, resource); await resource.process(); } finally { resource.close(); // Cleanup this.resources.delete(key); } } }

How do you implement async iterators for custom data sources?

Async iterators can be implemented using Symbol.asyncIterator: Example: class DataSource { constructor(data) { this.data = data; } async *[Symbol.asyncIterator]() { for (const item of this.data) { await new Promise(resolve => setTimeout(resolve, 100)); yield item; } } } async function processData() { const source = new DataSource([1, 2, 3]); for await (const item of source) { console.log(item); } }

What are the patterns for implementing rate limiting in async operations?

Rate limiting patterns include: 1) Token bucket algorithm, 2) Sliding window, 3) Fixed window counting, 4) Leaky bucket algorithm. Example: class RateLimiter { constructor(limit, interval) { this.limit = limit; this.interval = interval; this.tokens = limit; this.lastRefill = Date.now(); } async acquire() { const now = Date.now(); const timePassed = now - this.lastRefill; this.tokens += Math.floor(timePassed / this.interval) * this.limit; this.tokens = Math.min(this.tokens, this.limit); this.lastRefill = now; if (this.tokens <= 0) { throw new Error('Rate limit exceeded'); } this.tokens--; return true; } }

How do you handle timeouts in async operations?

Timeout handling includes: 1) Promise race with timeout promise, 2) AbortController integration, 3) Cleanup on timeout. Example: function withTimeout(promise, timeout) { const timeoutPromise = new Promise((_, reject) => { setTimeout(() => reject(new Error('Operation timed out')), timeout); }); return Promise.race([promise, timeoutPromise]); } async function fetchWithTimeout(url, timeout = 5000) { const controller = new AbortController(); const id = setTimeout(() => controller.abort(), timeout); try { const response = await fetch(url, { signal: controller.signal }); clearTimeout(id); return response; } catch (err) { clearTimeout(id); throw err; } }

How do you implement async dependency injection?

Async dependency injection patterns include: 1) Factory functions, 2) Async constructors, 3) Dependency containers. Example: class Container { constructor() { this.dependencies = new Map(); } async register(key, factory) { this.dependencies.set(key, factory); } async resolve(key) { const factory = this.dependencies.get(key); if (!factory) throw new Error(`No dependency found for ${key}`); return await factory(); } } class Service { static async create(container) { const dependency = await container.resolve('dependency'); return new Service(dependency); } }

What are the patterns for handling distributed events in Node.js?

Distributed event patterns include: 1) Message queues, 2) Pub/sub systems, 3) Event buses, 4) Webhook implementations. Example: class DistributedEventEmitter { constructor(redis) { this.redis = redis; this.handlers = new Map(); this.redis.subscribe('events'); this.redis.on('message', (channel, message) => { const event = JSON.parse(message); const handlers = this.handlers.get(event.type) || []; handlers.forEach(handler => handler(event.data)); }); } on(eventType, handler) { const handlers = this.handlers.get(eventType) || []; handlers.push(handler); this.handlers.set(eventType, handlers); } emit(eventType, data) { this.redis.publish('events', JSON.stringify({ type: eventType, data })); } }

How do you implement async middleware patterns?

Async middleware patterns include: 1) Pipeline pattern, 2) Chain of responsibility, 3) Composition pattern. Example: class MiddlewareChain { constructor() { this.middlewares = []; } use(middleware) { this.middlewares.push(middleware); return this; } async execute(context) { return this.middlewares.reduce((promise, middleware) => { return promise.then(() => middleware(context)); }, Promise.resolve()); } } const chain = new MiddlewareChain(); chain.use(async (ctx) => { ctx.validated = true; }).use(async (ctx) => { if (ctx.validated) ctx.processed = true; });

What are the strategies for handling backpressure in async streams?

Backpressure handling strategies include: 1) Implementing pause/resume mechanisms, 2) Buffer size limits, 3) Throttling, 4) Flow control. Example: class ThrottledStream extends Readable { constructor(source, rate) { super(); this.source = source; this.rate = rate; this.lastRead = Date.now(); } _read(size) { const now = Date.now(); const timeSinceLastRead = now - this.lastRead; if (timeSinceLastRead < this.rate) { setTimeout(() => this._read(size), this.rate - timeSinceLastRead); return; } this.lastRead = now; const chunk = this.source.read(size); this.push(chunk); } }

How do you implement async error boundaries?

Async error boundaries can be implemented using: 1) Higher-order functions, 2) Class wrappers, 3) Decorator patterns. Example: class AsyncBoundary { constructor(errorHandler) { this.errorHandler = errorHandler; } wrap(target) { return new Proxy(target, { get: (obj, prop) => { const value = obj[prop]; if (typeof value === 'function') { return async (...args) => { try { return await value.apply(obj, args); } catch (error) { return this.errorHandler(error); } }; } return value; } }); } } const safeFetch = new AsyncBoundary(error => console.error(error)) .wrap({ async fetch(url) { const response = await fetch(url); return response.json(); } });

What are the different module systems in Node.js?

Node.js supports multiple module systems: 1) CommonJS (require/exports): Traditional Node.js module system. Example: const fs = require('fs'); module.exports = { ... }. 2) ES Modules (import/export): Modern JavaScript module system. Example: import fs from 'fs'; export const handler = { ... }. 3) ECMAScript Modules in Node.js require either .mjs extension or { 'type': 'module' } in package.json.

How does Node.js resolve module dependencies?

Node.js module resolution follows these steps: 1) Core modules (like 'fs'), 2) Local modules with relative paths ('./myModule'), 3) node_modules lookup (starts from current directory, moves up), 4) Package.json 'main' field. Example resolution: require('mymodule') → looks in ./node_modules/mymodule → ../node_modules/mymodule → / etc. Resolution can be customized using NODE_PATH environment variable or package.json fields.

What is package.json and what are its key components?

package.json is a project manifest file containing: 1) Basic info (name, version, description), 2) Dependencies (dependencies, devDependencies), 3) Scripts (start, test, build), 4) Configuration (type, engines). Example: { 'name': 'my-app', 'version': '1.0.0', 'dependencies': { 'express': '^4.17.1' }, 'scripts': { 'start': 'node server.js' }, 'type': 'module' }. It's essential for npm package management and project configuration.

How do you manage dependencies using npm?

NPM dependency management includes: 1) Installing packages: npm install package-name, 2) Saving dependencies: --save or --save-dev flags, 3) Version control: semantic versioning (^, ~, exact versions), 4) Updating packages: npm update, 5) Auditing security: npm audit. Example managing a project: npm init npm install express --save npm install jest --save-dev npm update npm audit fix

What are peer dependencies and when should you use them?

Peer dependencies specify packages that must be installed by the consuming application. Used when: 1) Creating plugins/extensions, 2) Avoiding duplicate dependencies, 3) Ensuring compatibility. Example package.json: { 'name': 'my-plugin', 'peerDependencies': { 'react': '>=16.8.0', 'react-dom': '>=16.8.0' } }. The consuming application must install compatible versions of peer dependencies.

How do you handle circular dependencies in Node.js?

Circular dependencies can be handled through: 1) Restructuring code to avoid cycles, 2) Using dependency injection, 3) Moving shared code to a separate module. Example problem: // a.js const b = require('./b'); // b.js const a = require('./a'); Solution: Create shared module: // shared.js module.exports = { sharedFunction() {} }; Then import shared in both modules.

What is npm workspaces and how do you use it?

NPM workspaces enable managing multiple packages in a single repository: 1) Define workspaces in root package.json, 2) Share dependencies across packages, 3) Link local packages together. Example: { 'name': 'monorepo', 'workspaces': ['packages/*'], 'private': true }. Directory structure: /packages/pkg1/package.json /packages/pkg2/package.json. Commands work across all workspaces: npm install --workspace=pkg1

How do you optimize module loading performance?

Module loading optimization techniques: 1) Use module caching effectively, 2) Implement lazy loading, 3) Bundle modules for production, 4) Use path aliases. Example lazy loading: const getLodash = () => require('lodash'); function processData(data) { const _ = getLodash(); return _.groupBy(data, 'type'); } Cache example: const cache = {}; function requireFromCache(module) { if (!cache[module]) cache[module] = require(module); return cache[module]; }

What are the different ways to version Node.js packages?

Package versioning methods include: 1) Semantic Versioning (MAJOR.MINOR.PATCH), 2) Version ranges (^, ~, *, x), 3) Git URLs, 4) Local paths. Example package.json: { 'dependencies': { 'express': '^4.17.1', // Minor version updates 'lodash': '~4.17.21', // Patch updates only 'mylib': 'file:../mylib', // Local path 'private-pkg': 'git+ssh://git@github.com:org/repo.git' // Git URL } }

How do you publish and maintain npm packages?

Package publishing process: 1) Prepare package.json (name, version, files), 2) Create npm account, 3) npm login, 4) npm publish. Maintenance: 1) Version updates (npm version), 2) README and documentation, 3) Security updates, 4) Deprecation if needed. Example workflow: npm version patch npm publish npm deprecate my-package@"<2.0.0" "Critical security bug fixed in v2.0.0"

What is the role of package-lock.json?

package-lock.json ensures consistent installs across environments by: 1) Locking exact versions of dependencies, 2) Recording dependency tree, 3) Including integrity hashes, 4) Maintaining deterministic installs. Example: { 'name': 'project', 'lockfileVersion': 2, 'requires': true, 'packages': { 'node_modules/express': { 'version': '4.17.1', 'resolved': 'https://registry.npmjs.org/express/-/express-4.17.1.tgz', 'integrity': 'sha512-...' } } }

How do you handle native modules in Node.js?

Native modules management includes: 1) node-gyp for compilation, 2) Binary distribution using prebuilt packages, 3) Platform-specific installations. Example package.json: { 'dependencies': { 'bcrypt': '^5.0.1' }, 'scripts': { 'install': 'node-gyp rebuild' } } Installation handling: if (process.platform === 'win32') { module.exports = require('./binary/windows'); } else { module.exports = require('./binary/unix'); }

What are the security best practices for dependency management?

Security practices include: 1) Regular security audits (npm audit), 2) Version pinning for critical dependencies, 3) Using .npmrc for security settings, 4) Implementing lockfiles, 5) Automated vulnerability scanning. Example: { 'scripts': { 'preinstall': 'npm audit', 'audit-fix': 'npm audit fix' } } .npmrc configuration: audit=true save-exact=true package-lock=true

How do you implement module mocking in tests?

Module mocking approaches: 1) Jest mock functions, 2) Proxyquire for dependency injection, 3) Manual mocking. Example with Jest: jest.mock('./database', () => ({ query: jest.fn() })); Example with Proxyquire: const proxyquire = require('proxyquire'); const stubs = { './database': { query: () => Promise.resolve([]) } }; const module = proxyquire('./module', stubs);

What are the different module scoping patterns in Node.js?

Module scoping patterns include: 1) IIFE (Immediately Invoked Function Expression), 2) Revealing Module Pattern, 3) ES Modules with private fields, 4) Symbol-based privacy. Example: const createModule = () => { const privateVar = Symbol('private'); return { [privateVar]: 'hidden', publicMethod() { return this[privateVar]; } }; }; ES Module example: export class Module { #privateField = 'hidden'; getPrivate() { return this.#privateField; } }

How do you manage environment-specific dependencies?

Environment-specific dependency management: 1) Development vs production dependencies, 2) Optional dependencies, 3) Conditional installations, 4) Environment-specific builds. Example package.json: { 'dependencies': { 'express': '^4.17.1' }, 'devDependencies': { 'jest': '^27.0.0' }, 'optionalDependencies': { 'win-printer': '^1.0.0' }, 'scripts': { 'install': 'node scripts/conditional-install.js' } }

Explore More

HR Interview Questions

Why Prepare with Stark.ai for nodejs Interviews?

Role-Specific Questions

  • Backend Developer
  • Full-Stack Developer
  • DevOps Engineer

Expert Insights

  • Detailed explanations of Node.js event loop and asynchronous programming.

Real-World Scenarios

  • Practical challenges that simulate real-world server-side development.

How Stark.ai Helps You Prepare for nodejs Interviews

Mock Interviews

Simulate Node.js-specific interview scenarios.

Explore More

Practice Coding Questions

Solve Node.js challenges tailored for interviews.

Explore More

Resume Optimization

Highlight your Node.js expertise with an ATS-friendly resume.

Explore More

Tips to Ace Your nodejs Interviews

Master Async Programming

Understand promises, async/await, and callback patterns.

Practice API Design

Work with Express.js, REST APIs, and middleware.

Learn Performance Optimization

Explore clustering, caching, and database optimization.

Be Ready for System Design

Expect questions about scalability and microservices.

Ready to Ace Your Node.js Interviews?

Join thousands of successful candidates preparing with Stark.ai. Start practicing Node.js questions, mock interviews, and more to secure your dream role.

Start Preparing now
practicing