Intermediate Node.js Interview Questions
12 Node.js interview questions for developers with some experience (2 to 5 years): event-loop phases, streams and backpressure, Express middleware and errors, auth cookies and status codes. Each answer explains why the other options are wrong.
CoversApi designAuthBufferConfigEncodingError handlingEvent loopExpressHttpMiddlewareNode.jsScalingSecurityStreams
By Deepak KumarPublished Answers checked by Deepak
Take it as a timed test
- 12 questions
- 15 min
- Pass mark 60%
- Answers shown at the end
No sign-up. Your answers and scores stay in this browser.
This intermediate paper has 12 Node.js questions for developers with some experience with roughly 2 to 5 years of experience. It covers event-loop phases, streams and backpressure, Express middleware and errors, auth cookies and status codes. Ten questions are on this page with full explanations; the timed test also includes two questions that aren't shown here, so practise for understanding rather than memory.
How should you use this paper?
Answer each practice question before opening its explanation, and say your reasoning out loud the way you would in an interview. Then take the timed test: 15 minutes, a pass mark of 60%, with answers shown at the end. Your report breaks your score down by topic and difficulty, and you can retry only the questions you missed.
Practice questions with answers
Try each one before opening the answer. The explanation covers why the other options are wrong. The timed test also uses 2 questions that aren't shown here, so practise for understanding, not memory.
Inside an I/O callback, which runs first: setTimeout(…, 0) or setImmediate?
const fs = require('fs');
fs.readFile(__filename, () => {
setTimeout(() => console.log('timeout'), 0);
setImmediate(() => console.log('immediate'));
});Show answer and explanation
Answer: A. immediate, then timeout
An I/O callback runs in the poll phase. The next phase is check, where setImmediate callbacks run, and timers only come round on the following loop iteration. So inside an I/O callback the order is always immediate, then timeout. In the main module the order of these two is not guaranteed, because it depends on how long the loop took to start.
writable.write(chunk) returns false. What should your code do?
Show answer and explanation
Answer: A. Stop writing and wait for the stream's 'drain' event before continuing
false means the stream's internal buffer has reached its high-water mark: the data was accepted, but you are writing faster than the destination can take it. Respecting this is called handling backpressure. Pause and resume on 'drain', or use pipeline, which does it for you. Ignoring it lets memory grow without limit on big transfers.
Why is stream.pipeline(a, b, c, callback) safer than a.pipe(b).pipe(c)?
Show answer and explanation
Answer: A. It forwards errors from any stream and destroys all of them on failure, so nothing leaks
With chained .pipe(), an error in one stream isn't passed along, and the others can stay open, leaking file descriptors or sockets. pipeline wires up error handling across every stream, destroys them all when one fails, and reports a single error to your callback. The promise version from stream/promises lets you await it.
Which statements about Express middleware are true? Select all that apply.
Show answer and explanation
Answer: A. Middleware runs in the order it is registered + B. Each middleware must call next() or send a response + C. Error-handling middleware takes four arguments: (err, req, res, next)
Express keeps a list of middleware and runs it in registration order, so body parsing and auth must come before the routes that need them. A middleware that neither calls next() nor responds leaves the request hanging. Express recognises error handlers by their four parameters. app.use middleware runs for every HTTP method.
Why keep a session token in an httpOnly cookie rather than localStorage?
Show answer and explanation
Answer: A. Page JavaScript can't read an httpOnly cookie, so an XSS bug can't steal the token
Anything in localStorage can be read by any script on the page, including one injected through an XSS hole. An httpOnly cookie is sent with requests but is invisible to JavaScript. Pair it with Secure and SameSite=Lax or Strict, and protect state-changing requests from CSRF, since browsers attach cookies automatically.
In Express 5, a rejected promise from an async route handler reaches your error-handling middleware without extra code.
TrueFalse
Show answer and explanation
Answer: True
True. Express 5 catches rejected promises returned by handlers and middleware and passes the error to next(err) for you. Express 4 didn't, so async errors left requests hanging unless you wrapped every handler. Knowing which version a project uses matters, and the difference is a common follow-up question.
What does Node's cluster module do?
Show answer and explanation
Answer: A. Starts several Node.js processes that share one server port, so you use every CPU core
One Node.js process runs your JavaScript on one main thread, so it uses one core. cluster forks worker processes that share the listening port, letting a multi-core machine handle more requests. Each worker has its own memory, so in-process caches and sessions aren't shared. Many teams run several instances behind a load balancer or a process manager instead.
What is the byte length of Buffer.from('hé')?
console.log(Buffer.from('hé').length);Show answer and explanation
Answer: A. 3
Buffer.from encodes strings as UTF-8 by default. "h" takes one byte and "é" takes two, so the buffer is 3 bytes long, while the string's length is 2 characters. This difference matters for Content-Length headers, database column limits and anything that counts bytes; use Buffer.byteLength(str) for the real size.
Why should a .env file with API keys not be committed to Git?
Show answer and explanation
Answer: A. Anyone with access to the repository, now or in its history, could read the secrets
Once a secret is in Git history it is effectively public to everyone who can clone the repo, and deleting the file later doesn't remove it from old commits. Add .env to .gitignore, commit a .env.example with blank values, and keep real secrets in your host's settings or a secrets manager. Rotate any key that was ever committed.
Match each HTTP status code to when an API should send it.
- 201
- 400
- 401
- 404
- The caller isn't signed in or the token is invalid
- The resource doesn't exist
- The request body or parameters are invalid
- A new resource was created
Show answer and explanation
Answer: 201 → A new resource was created400 → The request body or parameters are invalid401 → The caller isn't signed in or the token is invalid404 → The resource doesn't exist
Correct status codes let clients react without parsing messages. 201 confirms a creation, ideally with a Location header. 400 is for malformed input. 401 means "who are you?", and 403 means "I know who you are, but you can't do this". 404 is for missing resources; some APIs return 404 instead of 403 to avoid revealing that something exists.
Answered them all? Take the same questions against the clock and get a topic-by-topic report.
Start the timed test