Interview Prep/Node.js

Top 50 Node.js Interview Questions & Answers 2025

Master Node.js interviews with 50+ questions on event loop, streams, performance, and backend architecture.

19 Questions~30 min read11 CategoriesUpdated 2025
Practice Node.js Quiz

Core Concepts

01 · 3q

The event loop handles async operations in phases: (1) Timers - setTimeout/setInterval callbacks, (2) Pending callbacks - I/O callbacks deferred, (3) Idle/Prepare - internal use, (4) Poll - retrieve new I/O events, (5) Check - setImmediate callbacks, (6) Close callbacks - socket.on("close"). process.nextTick and Promises run between phases in microtask queue.

Buffer handles raw binary data outside the V8 heap. Used for: file I/O, network protocols, encryption, image processing. Create with Buffer.from(), Buffer.alloc(). Buffers are fixed-size; use streams for large data. Security: use alloc() not allocUnsafe() unless you'll immediately fill it. Convert with toString(), toJSON().

Node.js uses EventEmitter for publish-subscribe patterns. Emitters trigger named events; listeners react to them. Core modules (HTTP, fs, streams) extend EventEmitter. Always handle "error" events or they throw. Use for: decoupled modules, plugin systems, real-time features. Don't overuse — complex event chains are hard to debug. Prefer Promises for sequential async flows.

Event Loop

02 · 1q

process.nextTick() executes immediately after current operation, before the event loop continues - it's in the microtask queue. setImmediate() executes in the Check phase of the event loop. nextTick has higher priority and can starve the event loop if used recursively. Use setImmediate for most cases; nextTick for critical callbacks that must run immediately.

Error Handling

03 · 1q

For callbacks: error-first pattern (err, result). For Promises: .catch() or try/catch with async/await. For EventEmitters: "error" event listener. For streams: "error" event. Global handlers: process.on("uncaughtException") and process.on("unhandledRejection"). Best practice: always handle errors explicitly, use error boundaries, log and monitor.

Streams

04 · 1q

Streams process data in chunks without loading everything into memory. Types: (1) Readable - data source (fs.createReadStream), (2) Writable - data destination (fs.createWriteStream), (3) Duplex - both readable/writable (TCP socket), (4) Transform - modify data while passing through (zlib.createGzip). Use pipe() to connect streams. Great for large files, real-time data.

Performance

05 · 4q

Clustering creates child processes (workers) that share the same server port, utilizing multiple CPU cores. The master process manages workers and distributes connections. Use for: CPU-intensive applications, improving throughput, high availability. Workers don't share memory; use Redis or IPC for shared state. PM2 provides built-in cluster management.

Worker Threads enable true parallelism for CPU-intensive tasks by running JavaScript in separate threads. Unlike child_process, they share memory via SharedArrayBuffer. Use for: heavy computations, image processing, data parsing. Don't use for I/O-bound tasks (use async). Communication via postMessage(). Each worker has its own event loop.

child_process spawns separate OS processes with separate memory (spawn, exec, fork). worker_threads creates threads sharing the same memory via SharedArrayBuffer and MessageChannel. child_process: true isolation, higher overhead, good for existing CLI tools. worker_threads: lower overhead, shared memory possible, better for CPU-intensive Node.js code. Both enable parallelism beyond the event loop.

Common leaks: global variables accumulating data, event listener buildup (not removing listeners), closures holding large references, unclosed streams/connections, caching without limits. Detection: process.memoryUsage(), --inspect flag with Chrome DevTools heap snapshots, clinic.js, node-memwatch. Fix: removeListener/removeAllListeners, WeakMap for caches, stream cleanup, bounded caches (lru-cache).

Modules

06 · 1q

CommonJS (require): synchronous loading, caches modules in require.cache, circular dependencies return partial exports. ES Modules (import): async loading, static analysis enables tree-shaking, live bindings. Node.js supports both; use .mjs extension or "type": "module" in package.json for ESM. Prefer ESM for new projects.

Express

07 · 1q

Middleware functions have access to request, response, and next(). They execute sequentially and can: modify req/res, end the request cycle, or call next(). Types: application-level (app.use), router-level (router.use), error-handling (4 params), built-in (express.json), third-party (cors, helmet). Order matters - declare before routes that use them.

Security

08 · 3q

Key practices: (1) Validate and sanitize input, (2) Use helmet for security headers, (3) Implement rate limiting, (4) Use HTTPS, (5) Keep dependencies updated (npm audit), (6) Don't expose stack traces in production, (7) Use parameterized queries for databases, (8) Implement proper authentication (JWT, sessions), (9) Set secure cookie flags, (10) Use environment variables for secrets.

Common approaches: JWT (stateless, signed tokens — store access token in memory, refresh in httpOnly cookie), Sessions (server-side state, session cookie — use express-session + Redis store), OAuth 2.0 (third-party providers — Passport.js). Best practices: hash passwords with bcrypt, short-lived access tokens, rotate refresh tokens, validate JWT signature and expiry on every request.

Rate limiting prevents abuse by restricting request frequency per client. Implementation: express-rate-limit for simple cases (in-memory window). For distributed apps: redis-based rate limiting (rate-limiter-flexible). Strategies: fixed window, sliding window, token bucket. Return 429 status with Retry-After header. Apply different limits to different routes (auth endpoints stricter). Use API gateway for infrastructure-level limiting.

Databases

09 · 1q

Always use connection pools — creating connections is expensive. For PostgreSQL: pg Pool or Sequelize pool settings. For MongoDB: mongoose maintains pool automatically. Key config: min/max pool size, idle timeout, connection timeout. In serverless (Lambda): use RDS Proxy or Mongoose singleton with connection reuse. Close pool on process exit. Never create a new connection per request.

Architecture

10 · 2q

Recommended structure: /src (source), /routes (express routers), /controllers (request handlers), /services (business logic), /models (data access), /middleware, /utils, /config. Principles: separation of concerns, controllers thin (delegate to services), services independent of framework. Use dependency injection for testability. config via environment variables (dotenv). Separate start.js from app.js for testing.

Use HTTP methods correctly (GET/POST/PUT/PATCH/DELETE). Resource-based URLs (/users/:id, not /getUser). HTTP status codes: 200 OK, 201 Created, 400 Bad Request, 401 Unauthorized, 403 Forbidden, 404 Not Found, 422 Validation, 429 Rate Limited, 500 Server Error. Pagination, filtering, sorting via query params. Versioning via URL (/api/v1) or header. Always validate input; return consistent error format.

DevOps

11 · 1q

PM2 is a process manager for Node.js. Features: automatic restart on crash, cluster mode (multiple CPU cores), log management, monitoring dashboard, zero-downtime deploys (pm2 reload), environment management. Use cluster mode to utilize all CPUs. ecosystem.config.js for multiple app configs. PM2 Plus for remote monitoring. Alternative: run as systemd service or in Docker container.

Ready to test your Node.js skills?

Practice with interactive quizzes and get instant feedback.

Start Free Practice