The Node.js questions that separate freshers are not simply, "What is Node?" They are, "In what order does this print?" and, "Why did your server run out of memory while serving a large file?" Node runs JavaScript on one main thread and handles asynchronous work around it, so interviewers test whether you understand the event loop rather than just the syntax placed on top.
Four areas come up repeatedly: execution order, streams, clustering and Express middleware. Once their mental models are clear, most follow-up questions become traceable.
The event loop in one picture
Use a compact loop that you can redraw: timers, pending callbacks, poll, check, close callbacks, then back to timers. The poll phase retrieves new I/O events and runs relevant I/O callbacks. setImmediate() callbacks run in check, while eligible setTimeout() callbacks run in timers.
Between phases, Node drains two important queues. It handles the process.nextTick queue first, then the Promise or general microtask queue. That extra priority explains why process.nextTick() can run before a resolved promise even when both are scheduled by the same synchronous code.

The output-ordering question everyone gets asked
Part A runs from the main module:
console.log('start');
process.nextTick(() => console.log('nextTick'));
Promise.resolve().then(() => console.log('promise'));
setTimeout(() => console.log('timeout'), 0);
setImmediate(() => console.log('immediate'));
console.log('end');Trace synchronous work first. start prints, the callbacks are scheduled, and end prints. The queues then drain, with nextTick before the Promise reaction. The first four lines are therefore exactly:
start
end
nextTick
promiseFrom the main module, the relative order of timeout and immediate is not guaranteed. The complete result is start, end, nextTick, promise, followed by either timeout, immediate or immediate, timeout.
Part B puts both registrations inside an I/O callback:
fs.readFile(__filename, () => {
setTimeout(() => console.log('timeout'), 0);
setImmediate(() => console.log('immediate'));
});Here the I/O callback runs in poll. The loop moves next to check before returning to timers, so the order is deterministic:
immediate
timeoutThe rule is more useful than memorising one output: locate where the callback is registered, identify its queue or phase, and then walk the loop.
Streams and backpressure
The memory question from the opening is really a streams question. Node has four main stream types. A readable produces data, a writable consumes it, a duplex can do both independently, and a transform is a duplex stream whose output is derived from its input. File reads, HTTP bodies and compression all fit this model.
readable.pipe(writable) moves bytes in chunks instead of loading the entire source at once. For byte streams (the default, non-object mode) in Node 22 and later, the default highWaterMark is 65536 bytes, or 64 KiB. It is a buffering threshold, not permission to keep accepting unlimited data.
When the writable's internal buffer fills, write() returns false. The readable pauses, then resumes after the writable emits 'drain'. This feedback is backpressure. It lets a fast producer match a slow consumer, which is why piping a 2 GB file can keep memory roughly flat while fs.readFileSync() attempts to load the whole file into memory.

Written out by hand, backpressure is a pause and a resume:
const rs = fs.createReadStream('big.log');
const ws = fs.createWriteStream('copy.log');
// pipe() does exactly this for you
rs.on('data', (chunk) => {
if (!ws.write(chunk)) rs.pause();
});
ws.on('drain', () => rs.resume());In real code, write stream.pipeline(rs, ws, callback) instead. It applies the same backpressure, forwards an error from either stream to one callback, and destroys both streams when one fails, so a stray 'error' event cannot take the process down.
Clustering and more than one core
The next question is about hardware: the server has eight cores, so why is Node using one? A single Node process runs JavaScript on one core. The cluster module can fork worker processes, commonly one per logical CPU reported by os.cpus().length, and those workers can share the same listening port. On Linux, the default scheduling policy distributes incoming connections among workers in round-robin fashion through the primary process.
The answer fits in one file:
const cluster = require('node:cluster');
const os = require('node:os');
const http = require('node:http');
if (cluster.isPrimary) {
for (let i = 0; i < os.cpus().length; i++) {
cluster.fork();
}
} else {
http.createServer(handler).listen(3000);
}Workers are separate processes with separate memory. worker_threads are different: they are threads within one process, can share memory, and suit CPU-heavy JavaScript that would otherwise block the main event loop. This distinction connects directly to the process and thread reasoning in Operating System interview questions for freshers.
Clustering increases the number of requests that can be served across cores. It does not make a blocking loop inside one worker harmless. That worker still stops handling its other callbacks until the loop completes.
Express middleware and the error-handling rule
Express questions land on one thing: what happens to an error thrown inside a route handler. Express runs middleware in registration order. Each middleware either sends a response, calls next() to continue, or calls next(err) to skip normal middleware and enter error handling.
A small chain makes the rule concrete:
app.use((req, res, next) => {
console.log(req.method, req.url);
next();
});
app.get('/user/:id', async (req, res, next) => {
try {
const user = await findUser(req.params.id);
res.json(user);
} catch (err) {
next(err);
}
});
app.use((err, req, res, next) => {
res.status(500).json({ error: 'Internal error' });
});Error-handling middleware has four arguments: (err, req, res, next). Register it after routes and normal middleware. If the signature or order is wrong, Express may treat the function as normal middleware or let the error fall through without your intended response. For the full request lifecycle, routing patterns and the double-response trap, read Express.js REST API routing, middleware and error handling.
Traps, interview format and your next step
Keep these four traps ready with the reason behind each:
A synchronous CPU loop blocks the event loop, so other callbacks in that process stall.
Recursive
process.nextTick()scheduling can starve I/O because that queue keeps taking priority.An unhandled
'error'event on a stream can terminate the process.setTimeout(fn, 0)schedules work; it does not run the function immediately.
Expect predict-the-output snippets followed by questions such as, "How would you stream this?" or, "How would you use all cores?" Both of those answers are written out above. Practise them from memory, trace real programs rather than memorising outputs, and keep the Node documentation as your reference. The broader Technical interview prep for core CS subjects helps connect these answers to OS, DBMS and networking follow-ups.
The short version is simple: queues decide callback order, backpressure protects memory, clustering adds processes, and four-argument middleware handles Express errors. Work these ideas in the Complete Node.js, Express.js and MongoDB course, then use the Coding Skills catalogue to continue. KnowledgeGate's question bank has more than 600 MERN-stack questions covering Node, Express and MongoDB, so practise by predicting before you execute.




