<?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: MANAS YADAV</title>
    <description>The latest articles on DEV Community by MANAS YADAV (@manas2297).</description>
    <link>https://dev.to/manas2297</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.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F251791%2F797b2a2c-ad3f-400b-b1b6-cc102a7c7384.JPG</url>
      <title>DEV Community: MANAS YADAV</title>
      <link>https://dev.to/manas2297</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/manas2297"/>
    <language>en</language>
    <item>
      <title>What Is Event Loop Lag in Node.js? How to Measure It (Part 1)</title>
      <dc:creator>MANAS YADAV</dc:creator>
      <pubDate>Tue, 13 Oct 2026 12:17:03 +0000</pubDate>
      <link>https://dev.to/manas2297/what-is-event-loop-lag-in-nodejs-how-to-measure-it-part-1-399g</link>
      <guid>https://dev.to/manas2297/what-is-event-loop-lag-in-nodejs-how-to-measure-it-part-1-399g</guid>
      <description>&lt;p&gt;Your Node.js API gets slow. The database looks fine. So do the downstream services. Yet p99 latency has tripled and even the health check takes 300ms.&lt;/p&gt;

&lt;p&gt;Often the problem is the event loop itself. Node runs your JavaScript on one thread, and when something keeps that thread busy, every other request in the process waits in line. That includes the ones that do almost nothing.&lt;/p&gt;

&lt;p&gt;That wait is called &lt;strong&gt;event loop lag&lt;/strong&gt;. It's one of the cheapest metrics you can add to a Node service, and one of the most useful.&lt;/p&gt;

&lt;p&gt;This is part 1 of a 3-part series:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;What lag is, how to measure it, and when to check it&lt;/strong&gt; (this post)&lt;/li&gt;
&lt;li&gt;The common causes and how to fix them&lt;/li&gt;
&lt;li&gt;CPU throttling: the lag your dashboard hides
Every number below comes from scripts I ran on Node 22 in a 4 vCPU Linux container. The code is in the post, so you can rerun it and get your own.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  How the Node.js event loop works (in 30 seconds)
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fcvo9fz0fpj1vhpcc6o1m.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fcvo9fz0fpj1vhpcc6o1m.png" alt="The Node.js event loop phases and a blocking callback holding up the queue" width="800" height="416"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Node's event loop goes round in phases: timers (&lt;code&gt;setTimeout&lt;/code&gt;, &lt;code&gt;setInterval&lt;/code&gt;), pending callbacks, poll (where most I/O callbacks run), check (&lt;code&gt;setImmediate&lt;/code&gt;) and close callbacks. After each callback, it drains the microtask queues (&lt;code&gt;process.nextTick&lt;/code&gt;, then promise callbacks).&lt;/p&gt;

&lt;p&gt;The part that matters: &lt;strong&gt;only one callback runs at a time&lt;/strong&gt;. Node can have thousands of sockets open, but if one callback runs for 130ms, nothing else in that process runs for 130ms. Your health check included.&lt;/p&gt;

&lt;h2&gt;
  
  
  What is event loop lag?
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fk2h6k232grqh18roa1w5.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fk2h6k232grqh18roa1w5.png" alt="A timer due at 10ms fires at 126ms because synchronous code is running. The 116ms difference is lag." width="800" height="320"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Schedule a timer for 10ms and note when it actually fires. At 10ms, the loop was free. At 126ms, something held the loop for about 116ms. That difference is event loop lag (Node calls it &lt;em&gt;event loop delay&lt;/em&gt;).&lt;/p&gt;

&lt;p&gt;It's queueing delay, paid before a callback's own work even starts, and it lands on every request handled in that window.&lt;/p&gt;

&lt;h2&gt;
  
  
  How to measure event loop lag in Node.js
&lt;/h2&gt;

&lt;p&gt;You could hand-roll the timer trick, but &lt;code&gt;perf_hooks&lt;/code&gt; already has &lt;code&gt;monitorEventLoopDelay&lt;/code&gt;: a histogram sampled by libuv, with percentiles. Pair it with &lt;strong&gt;event loop utilization (ELU)&lt;/strong&gt;, the fraction of time the loop spent running code instead of waiting for I/O.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// lag-metrics.js&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;monitorEventLoopDelay&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;performance&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;node:perf_hooks&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;histogram&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;monitorEventLoopDelay&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;resolution&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt; &lt;span class="c1"&gt;// sample every 10ms&lt;/span&gt;
&lt;span class="nx"&gt;histogram&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;enable&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;lastELU&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;performance&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;eventLoopUtilization&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="nf"&gt;setInterval&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;elu&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;performance&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;eventLoopUtilization&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;lastELU&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// delta since last report&lt;/span&gt;
  &lt;span class="nx"&gt;lastELU&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;performance&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;eventLoopUtilization&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

  &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="na"&gt;lag_p50_ms&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;histogram&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;percentile&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;50&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="nx"&gt;e6&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;// values are in nanoseconds&lt;/span&gt;
    &lt;span class="na"&gt;lag_p99_ms&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;histogram&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;percentile&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;99&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="nx"&gt;e6&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;lag_max_ms&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;histogram&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;max&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="nx"&gt;e6&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;elu&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;elu&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;utilization&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;toFixed&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="c1"&gt;// 0 = idle, 1 = always busy&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;

  &lt;span class="nx"&gt;histogram&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;reset&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="nx"&gt;_000&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;unref&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A few gotchas:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Values are in nanoseconds.&lt;/strong&gt; Divide by &lt;code&gt;1e6&lt;/code&gt; for milliseconds.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;There's a floor around the resolution.&lt;/strong&gt; With &lt;code&gt;resolution: 10&lt;/code&gt;, an idle process reports roughly 10ms, because the histogram includes its own sampling interval. Watch for movement above that floor.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Ignore the mean.&lt;/strong&gt; A loop that's fine 99% of the time and freezes for 500ms every few seconds has a lovely average and unhappy users. Look at p99 and max.
On Prometheus? &lt;code&gt;prom-client&lt;/code&gt;'s &lt;code&gt;collectDefaultMetrics()&lt;/code&gt; already exports &lt;code&gt;nodejs_eventloop_lag_p99_seconds&lt;/code&gt; and friends. You may have the data and just no panel for it.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Demo: one blocking call slows every route
&lt;/h2&gt;

&lt;p&gt;Two routes. &lt;code&gt;/ping&lt;/code&gt; does nothing. &lt;code&gt;/hash&lt;/code&gt; hashes a password with PBKDF2, either sync or async:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// blocking-server.js&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;http&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;node:http&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;crypto&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;node:crypto&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;promisify&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;node:util&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;pbkdf2&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;promisify&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;crypto&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;pbkdf2&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;MODE&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;MODE&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;sync&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nx"&gt;http&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;createServer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;url&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/hash&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;key&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;MODE&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;sync&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
      &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="nx"&gt;crypto&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;pbkdf2Sync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;secret&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;salt&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;200&lt;/span&gt;&lt;span class="nx"&gt;_000&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;64&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;sha512&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;// blocks the loop&lt;/span&gt;
      &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;pbkdf2&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;secret&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;salt&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;200&lt;/span&gt;&lt;span class="nx"&gt;_000&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;64&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;sha512&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;     &lt;span class="c1"&gt;// runs on the libuv threadpool&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;end&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;key&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;toString&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;hex&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;slice&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;end&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;pong&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}).&lt;/span&gt;&lt;span class="nf"&gt;listen&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;3000&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The load script fires 5 &lt;code&gt;/hash&lt;/code&gt; requests, then a &lt;code&gt;/ping&lt;/code&gt; every 10ms for a second:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// bench-ping.js (Node 18+ for global fetch)&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="kd"&gt;get&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;path&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;http://localhost:3000&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;path&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;r&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;r&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;text&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;lat&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[];&lt;/span&gt;

&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/ping&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// warm up&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;hashes&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;Array&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;from&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;length&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/hash&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;pings&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[];&lt;/span&gt;
  &lt;span class="k"&gt;for &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;t&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;performance&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;now&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="nx"&gt;pings&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;push&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/ping&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;lat&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;push&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;performance&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;now&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="nx"&gt;t&lt;/span&gt;&lt;span class="p"&gt;)));&lt;/span&gt;
    &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Promise&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;r&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;setTimeout&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;r&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;all&lt;/span&gt;&lt;span class="p"&gt;([...&lt;/span&gt;&lt;span class="nx"&gt;hashes&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;pings&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;
  &lt;span class="nx"&gt;lat&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;sort&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;a&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;b&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;a&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="nx"&gt;b&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;p&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;q&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;lat&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;Math&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;floor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;q&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;lat&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;))].&lt;/span&gt;&lt;span class="nf"&gt;toFixed&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`/ping p50=&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nf"&gt;p&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;0.5&lt;/span&gt;&lt;span class="p"&gt;)}&lt;/span&gt;&lt;span class="s2"&gt;ms p99=&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nf"&gt;p&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;0.99&lt;/span&gt;&lt;span class="p"&gt;)}&lt;/span&gt;&lt;span class="s2"&gt;ms max=&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nf"&gt;p&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)}&lt;/span&gt;&lt;span class="s2"&gt;ms`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;})();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;MODE&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nb"&gt;sync &lt;/span&gt;node blocking-server.js &amp;amp;   &lt;span class="c"&gt;# then: node bench-ping.js&lt;/span&gt;
&lt;span class="nv"&gt;MODE&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;async node blocking-server.js &amp;amp;  &lt;span class="c"&gt;# then: node bench-ping.js&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Feiwzerym4vqcojuv0n3w.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Feiwzerym4vqcojuv0n3w.png" alt="GET /ping latency: p99 734ms with pbkdf2Sync versus 7.6ms with async pbkdf2" width="800" height="352"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;On my run, a route that does &lt;em&gt;nothing&lt;/em&gt; went from a p99 of 7.6ms to 734ms. The only difference was one &lt;code&gt;Sync&lt;/code&gt; call in a different route. The async version hands the hashing to libuv's threadpool, so the main thread stays free to answer &lt;code&gt;/ping&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;That's the core idea of this whole series. Lag is a shared cost: whatever blocks the loop, every request pays for it.&lt;/p&gt;

&lt;h2&gt;
  
  
  When should you check event loop lag?
&lt;/h2&gt;

&lt;p&gt;It should always be on a dashboard. These are the moments to go and look at it on purpose:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;p99 is up, but the database and downstreams look normal.&lt;/strong&gt; The biggest signal. If no dependency is slow, the queue in front of your own code often is.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Fast endpoints slow down together.&lt;/strong&gt; If &lt;code&gt;/health&lt;/code&gt; or a trivial route slows at the same time as the heavy ones, something is holding the loop.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Timeouts and dropped connections under load.&lt;/strong&gt; A lagging loop misses socket deadlines: &lt;code&gt;ETIMEDOUT&lt;/code&gt;, &lt;code&gt;ECONNRESET&lt;/code&gt;, 502s from the load balancer, Kafka consumers kicked from their group for missed heartbeats.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Health checks fail or pods restart under load,&lt;/strong&gt; while the app "works fine" when you poke it by hand.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;After a deploy&lt;/strong&gt; that added a dependency, a serialization step, a bigger response, or a regex on user input.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;After changing CPU limits or instance sizes,&lt;/strong&gt; or moving clusters.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;During load tests.&lt;/strong&gt; Record lag p99 next to throughput. Where lag starts climbing is your real per-process capacity.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Before you scale out.&lt;/strong&gt; If the lag comes from throttling or one blocking call, more pods won't fix it.
For an HTTP API, a rough starting point: lag p99 that stays above 50 to 100ms deserves a look, and anything regularly in the hundreds of milliseconds is hurting users. Tune that to your own latency targets. A batch worker can put up with far more.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  How to act on event loop lag automatically
&lt;/h2&gt;

&lt;p&gt;Once you trust the number, put it to work:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Load shedding.&lt;/strong&gt; When lag crosses a threshold, return &lt;code&gt;503&lt;/code&gt; to new requests instead of taking work you can't finish in time. On Fastify, &lt;a href="https://github.com/fastify/under-pressure" rel="noopener noreferrer"&gt;&lt;code&gt;@fastify/under-pressure&lt;/code&gt;&lt;/a&gt; does this with &lt;code&gt;maxEventLoopDelay&lt;/code&gt;:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;  &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;fastify&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;register&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@fastify/under-pressure&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;maxEventLoopDelay&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1000&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;        &lt;span class="c1"&gt;// ms&lt;/span&gt;
    &lt;span class="na"&gt;maxEventLoopUtilization&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mf"&gt;0.98&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Fail readiness, not liveness.&lt;/strong&gt; On sustained high lag, fail the readiness probe so the pod drops out of rotation and recovers. Failing liveness restarts it, throws away a warm process and dumps its traffic on the others, which usually makes things worse.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Alert on sustained p99,&lt;/strong&gt; not single spikes.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  FAQ
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;What is event loop lag in Node.js?&lt;/strong&gt;&lt;br&gt;
The delay between when a callback is ready to run and when the event loop actually runs it. It grows when something keeps the main thread busy or stops the process from getting CPU time.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Is event loop lag the same as event loop delay?&lt;/strong&gt;&lt;br&gt;
Yes. Node's API calls it event loop delay (&lt;code&gt;monitorEventLoopDelay&lt;/code&gt;). "Lag" is the common name in dashboards and libraries.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What is a good event loop lag value?&lt;/strong&gt;&lt;br&gt;
There's no universal number. As a rough starting point for an HTTP API, a p99 that stays above 50 to 100ms deserves a look, and regular spikes in the hundreds of milliseconds are hurting users.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Does async/await prevent event loop lag?&lt;/strong&gt;&lt;br&gt;
No. &lt;code&gt;await&lt;/code&gt; only frees the loop while you wait on real I/O or a timer. CPU-heavy code inside an async function still blocks, and long promise chains can block too (part 2 shows this).&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What's the difference between event loop lag and event loop utilization?&lt;/strong&gt;&lt;br&gt;
Lag is how late callbacks run. Utilization (ELU) is the share of time the loop was busy running code. High lag with high ELU means busy code. High lag with low ELU usually means the process was paused, for example by CPU throttling (part 3).&lt;/p&gt;

&lt;h2&gt;
  
  
  Up next
&lt;/h2&gt;

&lt;p&gt;You now know what lag is and how to see it. Part 2 goes through what actually causes it: blocking JavaScript, bad regexes, sync I/O, big JSON, GC pauses and promise loops, each with a runnable example and a fix.&lt;/p&gt;

&lt;p&gt;If you add one metric to your Node services this week, make it lag p99 next to ELU.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;The numbers in this post are from one run on Node 22 in a 4 vCPU container. Yours will differ, and that's the point of running the scripts.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>node</category>
      <category>webdev</category>
      <category>performance</category>
      <category>javascript</category>
    </item>
    <item>
      <title>Stop Context Switching: Introducing Stitch, an Energy-Guided Developer Workspace 🧵</title>
      <dc:creator>MANAS YADAV</dc:creator>
      <pubDate>Sat, 03 Oct 2026 05:59:47 +0000</pubDate>
      <link>https://dev.to/manas2297/stop-context-switching-introducing-stitch-an-energy-guided-developer-workspace-4nif</link>
      <guid>https://dev.to/manas2297/stop-context-switching-introducing-stitch-an-energy-guided-developer-workspace-4nif</guid>
      <description>&lt;p&gt;Have you ever started your workday staring at a mountain of repositories, lost track of which PRs need your review, and felt completely drained before writing a single line of code?&lt;/p&gt;

&lt;p&gt;As developers, we are constantly context-switching between reviewing PRs, sketching out architectures, addressing bugs, and executing deep work. Traditional tools treat all these tasks equally, but our brains don't. That's why I built &lt;em&gt;Stitch&lt;/em&gt;—a productivity-first developer dashboard that groups and manages your GitHub repositories by your active energy level.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Vision: Work How You Feel
&lt;/h2&gt;

&lt;p&gt;The core philosophy behind &lt;strong&gt;Stitch&lt;/strong&gt; is simple: &lt;em&gt;match your tooling to your mental bandwidth.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Instead of overwhelming you with a wall of notifications, Stitch uses a floating panel that lets you switch between three energy modes. It filters your entire workspace based on what you actually have the capacity to handle right now:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;🔋 Low Energy:&lt;/strong&gt; Filters the workspace to show PR Reviews and open Issues. Perfect for the end of the day or right after lunch when you just want to clear the queue.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;⚡ Medium Energy:&lt;/strong&gt; Surfaces Tag Releases and Major Projects. Great for planning, syncing roadmaps, and cutting releases.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;🔥 High Energy:&lt;/strong&gt; Activates the "Focus Workspace" and Build monitoring. This is for deep work.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Stitch acts as a unified hub for both local clones and web-only remotes, securely utilizing GitHub OAuth without intermediate servers storing your code.&lt;/p&gt;

&lt;h2&gt;
  
  
  Beyond a Dashboard: The Potential of a Unified Workspace
&lt;/h2&gt;

&lt;p&gt;Stitch isn't just about reading data; it's about staying in the flow state. The Focus Workspace acts as a deep-work sandbox for your active repository, featuring:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Architecture Diagramming&lt;/strong&gt;: An interactive node-edge canvas (powered by React Flow) to map out and save your repo's architecture.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Native Productivity Tools&lt;/strong&gt;: A built-in 25/5/15 Pomodoro timer, scoped markdown scratchpads, and a focus checklist.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Live Build Runner&lt;/strong&gt;: Stream live build and linting outputs via SSE directly in the UI.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Remote Roadmap Sync&lt;/strong&gt;: Automatically reads and writes roadmap items directly to a remote GitHub issue.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;AI Provider Monitor&lt;/strong&gt;: A dedicated utility to inspect and clean up disk usage from local AI tool caches (Gemini, Claude, Cursor, etc.).&lt;/p&gt;

&lt;h2&gt;
  
  
  The Tech Stack
&lt;/h2&gt;

&lt;p&gt;Stitch is built to be fast, local, and flexible. You can run it as a web app or as a standalone native desktop application.&lt;/p&gt;

&lt;p&gt;Backend: Go 1.24+ (REST API)&lt;/p&gt;

&lt;p&gt;Frontend: React 19, TypeScript, Vite, Zustand&lt;/p&gt;

&lt;p&gt;Desktop Wrapper: Wails v2&lt;/p&gt;

&lt;p&gt;Diagrams: React Flow&lt;/p&gt;

&lt;h2&gt;
  
  
  Let's Build This Together (Hacktoberfest is Open! 🎃)
&lt;/h2&gt;

&lt;p&gt;Stitch is currently in its early stages, and I am actively looking for collaborators to help shape its future. Whether you are passionate about developer productivity, love writing Go backends, or want to flex your React 19 skills, there is a place for you here.&lt;/p&gt;

&lt;p&gt;I’ve tagged several issues with good first issue, making it easy to jump in—and yes, Stitch is participating in Hacktoberfest!&lt;/p&gt;

&lt;p&gt;How you can help:&lt;/p&gt;

&lt;p&gt;Frontend: Improving the UI/UX, adding new visualization components, or expanding the Focus Workspace tools.&lt;/p&gt;

&lt;p&gt;Backend: Optimizing the Go server, expanding the GitHub CLI integrations, or enhancing the AI cache monitoring logic.&lt;/p&gt;

&lt;p&gt;Ideas &amp;amp; Feedback: Try it out, break it, and open an issue with your feature requests.&lt;/p&gt;

&lt;p&gt;If the idea of an energy-guided workflow resonates with you, check out the repository, star it, and let's stitch together a better way to work.&lt;/p&gt;

&lt;p&gt;👉 &lt;a href="https://github.com/manas2297/stitch" rel="noopener noreferrer"&gt;Check out Stitch on GitHub&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;I'd love to hear your thoughts in the comments! How do you currently manage context switching across dozens of repositories?&lt;/p&gt;
&lt;/blockquote&gt;

</description>
      <category>opensource</category>
      <category>hacktoberfest</category>
      <category>go</category>
      <category>react</category>
    </item>
    <item>
      <title>The Meat Proxy Engineering</title>
      <dc:creator>MANAS YADAV</dc:creator>
      <pubDate>Fri, 02 Oct 2026 12:01:26 +0000</pubDate>
      <link>https://dev.to/manas2297/the-artifact-engineers-4ig4</link>
      <guid>https://dev.to/manas2297/the-artifact-engineers-4ig4</guid>
      <description>&lt;p&gt;I've noticed a new breed of engineers emerging in the industry lately. A friend recently coined the term "meat proxy" for them, and it feels incredibly accurate.&lt;/p&gt;

&lt;p&gt;Picture this: a Staff Engineer sharing raw Claude artifacts with a casual "maybe," shifting the burden onto the rest of the team to verify what their AI actually generated.&lt;/p&gt;

&lt;p&gt;What exactly makes someone a meat proxy? It usually comes down to three things:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Zero-Value Routing: They act as a simple conduit between an AI and the team chat or codebase. They don't process or filter the information; they just forward it.&lt;/li&gt;
&lt;li&gt;By dropping a raw artifact with a "maybe this works," they outsource the actual engineering—verification, testing, and edge-case handling—to whichever unlucky teammate reviews their work.&lt;/li&gt;
&lt;li&gt;They generate massive volumes of code or architecture documents incredibly fast, but the net productivity of the team actually drops because of the massive cognitive load pushed onto reviewers.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Let me know if you have seen a meat proxy&lt;/p&gt;

</description>
      <category>ai</category>
      <category>llm</category>
      <category>softwareengineering</category>
      <category>programming</category>
    </item>
  </channel>
</rss>
