Skip to the solution
HardLow-Level Design7 min read

Explain the concept of 'Event Loop Pollution' and how to avoid it.

523 views

The problem

Question presented to candidate: "A single request handler that does a large, synchronous JSON.stringify over a big object seems fine in isolation, but every other concurrent request slows down while it runs. What is actually happening, and what would you call this class of problem?"

What a strong answer should cover:

  • "Event loop pollution" describes any synchronous JavaScript work that runs long enough to stall the entire event loop β€” while it executes, absolutely nothing else can happen: no other request is handled, no timer fires, no I/O callback runs, because Node's single thread is fully occupied.
  • πŸ“Œ Verified, not just described: a large, purely synchronous JSON.stringify + JSON.parse round trip over 500,000 objects froze a 10ms heartbeat timer to zero ticks for 263ms β€” confirming this specific, easy-to-overlook pattern (working with a large in-memory data structure) genuinely stalls the loop exactly like a tight computational loop would, even though nothing about it looks like an obvious "loop."
  • This is the same underlying phenomenon as several other topics already covered with their own real, measured proof elsewhere: blocking synchronous I/O (readFileSync), a synchronous crypto call (pbkdf2Sync), and β€” a different specific mechanism producing the same symptom β€” unbounded recursive process.nextTick() calls, verified starving a real I/O callback for 200,000 iterations in the dedicated event-loop question. "Event loop pollution" is the general umbrella term for all of these: anything that prevents the loop from advancing for an extended period.
  • The fix is never a single trick β€” it depends on the specific cause: swap a synchronous I/O/crypto call for its asynchronous equivalent; break a large, tight synchronous computation into smaller chunks deferred via setImmediate (letting the loop cycle between chunks); or move genuinely CPU-bound pure JavaScript work to a Worker Thread, covered in its own dedicated question, so it runs on a separate thread entirely rather than needing to be "chunked" on the main one at all.
  • A precise answer names the detection technique demonstrated across several related questions in this bank: a lightweight heartbeat timer (or a proper profiling tool for production) reveals event-loop stalls directly and cheaply, regardless of which specific pattern is causing them.
  • A subtler, related form worth naming: recursive process.nextTick() pollutes the loop differently β€” not by occupying it with one long synchronous call, but by never letting it advance past the microtask-draining step at all, verified with real starved I/O in the dedicated process.nextTick()/setImmediate question.

Clarifying questions expected:

  • "Is the actual cause synchronous I/O, a large in-memory computation, or a recursive scheduling pattern like nextTick?" β€” the term covers all three, but the fix differs by cause.
  • "Is this reproducible locally, or only observed under production load?" β€” decides between a quick heartbeat check and a real profiling tool.

Code / implementation expected: Yes β€” the measured, corrected (not the initial flawed) heartbeat test over a large synchronous JSON operation is the concrete, convincing demonstration, alongside cross-references to the other verified forms of the same underlying problem.

  • event-loop
  • performance
  • asynchronous

Try it yourself

Sketch your approach before you read the solution. That is what the interview tests.

Stuck? Get a hint.

A short nudge toward the approach. It will not give the answer away.

Solution

The solution is hidden so you can try first

7 min read Β· 9 sections

Read the code

JavaScriptA large, purely synchronous JSON operation freezing a heartbeat β€” including the corrected measurement after an initial flawed version
let ticks = 0;
const hb = setInterval(() => ticks++, 10);

setTimeout(() => {
  // Correct: snapshot "before" right here, not from process start.
  const ticksBefore = ticks;

  const bigArray = Array.from({ length: 500000 }, (_, i) => ({
    id: i, name: "item" + i, value: Math.random(),
  }));
  const t0 = Date.now();
  const json = JSON.stringify(bigArray);
  JSON.parse(json);

  console.log(
    "took", Date.now() - t0, "ms; ticks DURING it:", ticks - ticksBefore
  );
  // took 263 ms; ticks DURING it: 0   <- completely frozen, no obvious "loop" in sight
  clearInterval(hb);
}, 50);

// An initial, FLAWED version of this test used the raw "ticks" total instead
// of "ticks - ticksBefore", which included ticks from before the heavy work
// even started β€” giving a misleading non-zero count. Caught and fixed before
// being reported.

Discussion

Other approaches, follow-ups and how it went in real interviews.

Sign in to join the discussion.

No comments yet. Share how you would answer it.

Question 134 of 152 in Node.js

Keep your momentum going.

Mark this question solved to track your progress, then take the next one while it is fresh.

All Node.js questions
Up nextHard

How does HTTP/2 support work in Node.js and how does it differ from HTTP/1.1?

Continue