Node.js mock interview: backend questions by voice
This Node.js mock interview is for backend and full-stack developers preparing for junior, middle or senior roles, including Node.js interview questions for experienced engineers. The AI interviewer asks about the event loop, streams, async error handling, scaling, performance and security, and you answer out loud like in a real call. Pick a level or upload your resume or a job description, and get a scored report on technical accuracy, completeness and clarity.
What the Node.js interview covers
Event loop and libuv
Event loop phases (timers, poll, check, close), where process.nextTick and promise microtasks run, and which work libuv offloads to its thread pool (fs, dns.lookup, crypto, zlib).
Streams and backpressure
Readable, Writable, Duplex and Transform streams, highWaterMark, what happens when write() returns false, and why stream.pipeline beats manual .pipe() chains for error handling and cleanup.
Async patterns and error handling
Callbacks, promises and async/await, Promise.all vs allSettled, cancellation with AbortController, and what to do on unhandledRejection and uncaughtException.
Worker threads, cluster and scaling
When CPU-bound work needs worker_threads, how cluster or a process manager uses multiple cores, and why most production setups scale with stateless containers behind a load balancer.
Performance and memory leaks
Spotting a blocked event loop, profiling with --cpu-prof and Chrome DevTools, reading heap snapshots, and the usual leak sources: global caches, listeners and closures that are never released.
Security
Injection and prototype pollution, input validation, secrets handling, dependency and supply-chain risk (npm audit, lockfiles), rate limiting and safe defaults for HTTP headers.
HTTP, APIs and frameworks
Express middleware, Fastify plugins and schema validation, NestJS modules and DI, REST vs GraphQL trade-offs, graceful shutdown and connection keep-alive.
Testing
Unit vs integration tests with node:test, Jest or Vitest, mocking timers and network calls, testing against a real database in containers, and keeping tests fast and deterministic.
Node.js interview questions by level
Junior
Node.js runs JavaScript on a single thread. How does it handle thousands of concurrent requests?
What a strong answer covers:JavaScript runs on one thread, but I/O is non-blocking: Node hands sockets to the OS (epoll, kqueue, IOCP) and some operations like file system calls to the libuv thread pool. When an operation completes, its callback is queued and the event loop runs it. This works well for I/O-heavy workloads, but a single long CPU-bound task blocks every other request.
What is the difference between process.nextTick, setImmediate and setTimeout(fn, 0)?
What a strong answer covers:process.nextTick callbacks run right after the current operation, before promise microtasks and before the event loop continues. setTimeout(fn, 0) runs in the timers phase after at least 1 ms, and setImmediate runs in the check phase right after poll. Inside an I/O callback setImmediate always fires before the timeout; in the main module their order is not guaranteed. Recursive nextTick calls can starve I/O.
What are the differences between CommonJS and ES modules in Node.js?
What a strong answer covers:CommonJS uses require and module.exports, loads synchronously and is the default for .js files without "type": "module". ES modules use import/export, are statically analyzable, support top-level await and are chosen by .mjs or "type": "module". ESM has no __dirname or require by default (you use import.meta.dirname or import.meta.url), and recent Node versions can require() synchronous ES modules.
How do you handle errors in callbacks, promises and async/await?
What a strong answer covers:Node-style callbacks follow the error-first convention, so you check the err argument before using the result. With promises you attach .catch, and with async/await you wrap awaits in try/catch or let the error propagate to a central handler. A forgotten await or a missing catch leads to an unhandled rejection, which crashes the process by default since Node 15.
What is middleware in Express and how does the order matter?
What a strong answer covers:Middleware is a function (req, res, next) that runs in the order it is registered and can modify the request, end the response or call next() to pass control on. Order matters: body parsers and auth must run before route handlers, and the error handler with four arguments (err, req, res, next) goes last. In Express 5 rejected promises from async handlers are passed to the error handler automatically.
Middle
Explain streams and backpressure. What happens if you ignore backpressure?
What a strong answer covers:Streams process data in chunks instead of loading it all into memory. Backpressure is the signal that a consumer is slower than the producer: write() returns false once the buffer passes highWaterMark, and the producer should pause until the drain event. If you ignore it, data piles up in memory and the process can run out of heap. stream.pipeline (or its promise version) handles backpressure, propagates errors and destroys all streams on failure.
Compare Promise.all, Promise.allSettled, Promise.race and Promise.any. When would you use each?
What a strong answer covers:Promise.all resolves when all succeed and rejects on the first failure, so it fits when every result is required. allSettled waits for all and returns each status, useful for batch jobs where partial failure is fine. race settles with the first promise to settle, typically for timeouts, and any resolves with the first success, ignoring failures until all fail. None of them cancel the remaining work, so for real cancellation you pass an AbortSignal.
What can block the event loop, and how do you detect and fix it?
What a strong answer covers:Synchronous CPU work blocks it: heavy loops, JSON.parse or stringify of large payloads, sync fs or crypto calls, and catastrophic regex backtracking. You detect it with event loop delay metrics (perf_hooks.monitorEventLoopDelay), APM tools or a CPU profile. Fixes include moving CPU work to worker threads or a separate service, splitting work into chunks, streaming large payloads and using async APIs.
How would you find and fix a memory leak in a Node.js service?
What a strong answer covers:First confirm the leak: heap usage grows steadily across GC cycles under constant load rather than levelling off. Then take two or three heap snapshots over time (via --inspect, DevTools or --heapsnapshot-signal) and compare them to see which objects keep growing and what retains them. Typical causes are unbounded in-memory caches or maps, event listeners never removed, closures holding large objects and timers not cleared. The fix is to bound or expire caches, remove listeners and verify with a load test.
How do you implement graceful shutdown for an HTTP service?
What a strong answer covers:On SIGTERM you stop accepting new connections with server.close(), mark the service as not ready so the load balancer stops routing traffic, and let in-flight requests finish. Then you close idle keep-alive connections, drain queues, and close database pools and other clients. A hard timeout forces exit if something hangs, so the orchestrator does not have to SIGKILL the process mid-request.
Senior
When would you use worker_threads, cluster, child_process or simply more instances?
What a strong answer covers:worker_threads run JavaScript in parallel inside one process with shared memory options (SharedArrayBuffer, transferable objects), good for CPU-heavy tasks like image processing or parsing, usually via a pool. cluster forks processes that share a server port to use all cores, but in containerized setups one process per container with horizontal scaling is usually simpler. child_process is for running external programs or isolating risky work. The choice depends on whether the bottleneck is CPU, isolation or throughput.
p99 latency of your Node.js API spiked in production while CPU looks normal. How do you investigate?
What a strong answer covers:I would check event loop delay and GC pauses first, then look at downstream calls with distributed tracing to see whether the database, cache or a third-party API slowed down. Other common causes are an exhausted connection pool, a saturated libuv thread pool (default size 4) from fs, dns.lookup or crypto calls, and missing timeouts so requests queue behind slow ones. I would correlate with recent deploys and traffic, reproduce under load and confirm the fix with metrics.
What is your strategy for unhandledRejection and uncaughtException in production?
What a strong answer covers:After an uncaught exception the process state is unknown, so the safe approach is to log the error with context, flush logs and metrics, and exit with a non-zero code so the supervisor restarts it. Trying to keep running risks corrupted state and leaked resources. Unhandled rejections crash by default in modern Node, and the real fix is preventing them with proper awaits, centralized error handling and lint rules like no-floating-promises.
How would you pass request context such as a trace ID through all async calls without passing it manually?
What a strong answer covers:I would use AsyncLocalStorage from node:async_hooks: start a store per request in middleware with als.run(), and any code in that async chain can read it, for example in the logger. It is the basis for request-scoped logging and tracing in OpenTelemetry and frameworks like NestJS. I would keep the store small, avoid using it as a hidden dependency injection mechanism, and know that context can be lost with some custom callback-based libraries.
How do you secure a Node.js API and its dependencies?
What a strong answer covers:At the code level: validate input with schemas, use parameterized queries, guard against prototype pollution when merging user objects, set security headers, and add rate limiting and proper authentication. For the supply chain: commit the lockfile, install with npm ci, run npm audit or a scanner in CI, minimize dependencies and be careful with install scripts. At runtime: run as a non-root user, keep secrets out of code and logs, stay on a supported LTS version, and consider the Node permission model to restrict fs or child process access.
How the Node.js mock interview works
- Pick Node.js (and any other technologies from your stack), your level and the interview language: English, Ukrainian or Russian. Or upload your resume and a job description.
- Answer each question out loud, the way you would with a real interviewer.
- Get a score for every answer on technical accuracy, completeness and clarity, plus a report with your weak spots.
How to answer Node.js questions out loud
- →For event loop questions, name the phases in order (timers, pending callbacks, poll, check, close) and say where nextTick and promise microtasks fit; a clear sequence sounds more confident than a vague "it is asynchronous".
- →Tie every concept to a production consequence: a blocked event loop means rising latency for all users, ignored backpressure means memory growth, an unhandled rejection means a crashed process.
- →When asked "how would you debug X", walk through steps: what metric you check first, which tool you use (CPU profile, heap snapshot, tracing), and how you confirm the fix.
- →Name concrete APIs instead of describing them: stream.pipeline, AbortController, AsyncLocalStorage, worker_threads, server.close(). It shows hands-on experience in a few words.
- →For framework questions, start with the underlying Node.js mechanism, then mention how Express, Fastify or NestJS wraps it, so the answer holds up even if the interviewer uses a different framework.
FAQ
Do I write code during the Node.js mock interview?
No. There is no live coding editor: the AI asks verbal questions and you answer by voice, explaining concepts, trade-offs and how you would solve a problem. It trains the part of the interview where you have to talk through Node.js internals and design decisions clearly.
Can I combine Node.js with TypeScript, PostgreSQL or other technologies?
Yes. When choosing technologies you can pick several, for example Node.js with TypeScript and PostgreSQL, and the questions will mix them the way a backend interview usually does. You can also upload your resume or a job description to get questions based on the actual stack in the role.
Will I get Express or NestJS questions?
Framework questions come up where they are relevant, but the focus is on Node.js itself: the event loop, streams, async error handling, performance and security. If a job description you upload mentions a specific framework, the questions follow it.
How much does a Node.js mock interview cost?
Your first interview with up to 5 questions is free. After that you pay per interview, starting at $1.75, with no subscription. One interview can have up to 50 questions.