<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Hluf Abebe</title>
    <description>The latest articles on DEV Community by Hluf Abebe (@hluf).</description>
    <link>https://dev.to/hluf</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F993920%2F1e3c611b-b01f-4016-9363-31581e07ccf8.JPG</url>
      <title>DEV Community: Hluf Abebe</title>
      <link>https://dev.to/hluf</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/hluf"/>
    <language>en</language>
    <item>
      <title>How process.nextTick() Starves the Event Loop (A Node.js Pitfall)</title>
      <dc:creator>Hluf Abebe</dc:creator>
      <pubDate>Mon, 18 Aug 2025 08:04:25 +0000</pubDate>
      <link>https://dev.to/hluf/how-processnexttick-starves-the-event-loop-a-nodejs-pitfall-1ab1</link>
      <guid>https://dev.to/hluf/how-processnexttick-starves-the-event-loop-a-nodejs-pitfall-1ab1</guid>
      <description>&lt;p&gt;👀 Question: What do you think this code prints when it runs?&lt;br&gt;
💡 Guess the output before reading further!&lt;br&gt;
❓ Have you ever been told to never block the event loop? Why do you think that is?&lt;br&gt;
`&lt;br&gt;
setTimeout(() =&amp;gt; { console.log("time out") }, 0);&lt;br&gt;
setImmediate(() =&amp;gt; { console.log("immediate"); });&lt;/p&gt;

&lt;p&gt;function callNextTick() {&lt;br&gt;
  process.nextTick(callNextTick); &lt;br&gt;
}&lt;br&gt;
callNextTick();&lt;/p&gt;

&lt;p&gt;console.log("This is a weird code");`&lt;br&gt;
To understand why this code completely blocks the event loop, we need to understand Node.js's asynchronous execution model.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Expected Behavior (Without nextTick)&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Normally, the event loop processes tasks in phases:&lt;/p&gt;

&lt;p&gt;Timers Phase → Executes setTimeout (even with 0ms delay).&lt;/p&gt;

&lt;p&gt;Check Phase → Executes setImmediate.&lt;/p&gt;

&lt;p&gt;But here, both setTimeout and setImmediate will never get a chance to execute. Why is that?&lt;/p&gt;

&lt;p&gt;Understanding process.nextTick()&lt;/p&gt;

&lt;p&gt;Unlike setTimeout or setImmediate, process.nextTick() is not part of the normal event loop phases.&lt;/p&gt;

&lt;p&gt;It has its own special queue called the nextTickQueue.&lt;/p&gt;

&lt;p&gt;Callbacks in this queue run right after the current code finishes, before the event loop moves to any phase.&lt;/p&gt;

&lt;p&gt;How the Code Executes Step by Step&lt;/p&gt;

&lt;p&gt;1.setTimeout(() =&amp;gt; { console.log("time out") }, 0) is scheduled for the timers phase.&lt;br&gt;
2.setImmediate(() =&amp;gt; { console.log("immediate"); }) is scheduled for the check phase. &lt;br&gt;
3.callNextTick() is defined and immediately called. &lt;br&gt;
4.process.nextTick(callNextTick) adds the function to the nextTick queue. &lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;The synchronous line console.log("This is a weird code") executes.&lt;/li&gt;
&lt;li&gt;Node checks the nextTick queue after the current code finishes.&lt;/li&gt;
&lt;li&gt;callNextTick runs from the nextTick queue. &lt;/li&gt;
&lt;li&gt;Inside callNextTick, process.nextTick(callNextTick) schedules itself again.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Steps 6–8 repeat infinitely, because nextTick always runs before the event loop moves to any phase.&lt;/p&gt;

&lt;p&gt;Result: The event loop never reaches timers, I/O, or check phases, so setTimeout and setImmediate callbacks are never executed. This is called starving the event loop or blocking the event loop.&lt;/p&gt;

&lt;p&gt;Key Takeaways&lt;/p&gt;

&lt;p&gt;✅ nextTick is not part of the event loop → It runs before the loop proceeds.&lt;/p&gt;

&lt;p&gt;✅ Recursive nextTick = Event Loop Blockage → Starves timers, I/O, and setImmediate.&lt;/p&gt;

&lt;p&gt;✅ Avoid nextTick recursion → Use setImmediate if you need to defer execution without blocking.&lt;/p&gt;

</description>
    </item>
  </channel>
</rss>
