<?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: Aniket Misra</title>
    <description>The latest articles on DEV Community by Aniket Misra (@aniket_misra_e47d1564ab7b).</description>
    <link>https://dev.to/aniket_misra_e47d1564ab7b</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%2F3898086%2F9a9ac2ea-daea-42ff-8ba1-17ae767ab2f6.png</url>
      <title>DEV Community: Aniket Misra</title>
      <link>https://dev.to/aniket_misra_e47d1564ab7b</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/aniket_misra_e47d1564ab7b"/>
    <language>en</language>
    <item>
      <title>Escaping the Event Loop — A Deep Dive into worker_threads (Part 3/3)</title>
      <dc:creator>Aniket Misra</dc:creator>
      <pubDate>Tue, 04 Aug 2026 23:25:00 +0000</pubDate>
      <link>https://dev.to/aniket_misra_e47d1564ab7b/escaping-the-event-loop-a-deep-dive-into-workerthreads-part-33-11oj</link>
      <guid>https://dev.to/aniket_misra_e47d1564ab7b/escaping-the-event-loop-a-deep-dive-into-workerthreads-part-33-11oj</guid>
      <description>&lt;p&gt;In part 1, we built the core stack/microtask/macrotask model. In part 2, we saw how the browser and Node implement that model differently — rendering interleaved with tasks in the browser, libuv's phase-based loop in Node.&lt;/p&gt;

&lt;p&gt;Both of those posts share an unspoken assumption: your callbacks are fast. A few milliseconds, do their thing, return, let the loop move on. But what happens when that assumption breaks? What happens when you genuinely need to do slow, CPU-bound work — and there's no I/O to wait on, no callback to defer, just raw computation that has to happen?&lt;/p&gt;

&lt;p&gt;That's what this post is about. No amount of clever queue ordering saves you here. You need actual parallelism, and in Node, that means &lt;code&gt;worker_threads&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  The problem worker_threads solves
&lt;/h2&gt;

&lt;p&gt;Everything from parts 1 and 2 works because the &lt;em&gt;actual JS execution&lt;/em&gt; — the code inside your callbacks — is assumed to be short. The event loop is brilliant at making single-threaded JS &lt;em&gt;feel&lt;/em&gt; concurrent when the bottleneck is I/O: waiting on a database, a file read, a network response. While you wait, the thread is free to do other things.&lt;/p&gt;

&lt;p&gt;But CPU-bound work is a different beast entirely. Consider this:&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="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;fibonacci&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;n&lt;/span&gt;&lt;span class="p"&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;n&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;n&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;fibonacci&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;n&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="o"&gt;+&lt;/span&gt; &lt;span class="nf"&gt;fibonacci&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;n&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;2&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;server&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;http&lt;/span&gt;&lt;span class="dl"&gt;'&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="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;/fib&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;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;fibonacci&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;40&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// this takes a few seconds&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="s2"&gt;`Result: &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;return&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;OK&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="nx"&gt;server&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;Hit &lt;code&gt;/fib&lt;/code&gt;, and for however long that synchronous computation runs, &lt;strong&gt;the entire server is frozen.&lt;/strong&gt; Not just that request — every request. No other client's &lt;code&gt;/OK&lt;/code&gt; request gets served, no timers fire, no I/O callbacks run, because the single JS thread is stuck inside &lt;code&gt;fibonacci(40)&lt;/code&gt; and the event loop can't do anything until the call stack unwinds.&lt;/p&gt;

&lt;p&gt;This is the single most common misunderstanding about Node's concurrency model: async I/O doesn't make your CPU-bound code non-blocking. &lt;code&gt;fs.readFile&lt;/code&gt; doesn't block because the actual disk read happens off the JS thread, in libuv's thread pool, and only the (fast) callback runs on the JS thread. But a tight synchronous loop, a big JSON parse, a hash computation, image processing — there's no I/O to hand off. It's just your code, doing math, on the one thread you've got.&lt;/p&gt;

&lt;p&gt;You have three tools in Node for genuinely parallel work, and knowing which one to reach for actually matters.&lt;/p&gt;

&lt;h2&gt;
  
  
  worker_threads vs child_process vs cluster
&lt;/h2&gt;

&lt;p&gt;These get confused constantly because they all sound like "run more stuff at once." They solve different problems.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;code&gt;child_process&lt;/code&gt;&lt;/strong&gt; spawns an entirely separate OS process, potentially running a different program altogether (a shell command, a Python script, another Node script). Full isolation — separate memory space, separate V8 instance. Good for running external programs or when you want maximum isolation (a crash in the child can't take down the parent). Heavier to spin up, and communication happens via serialized IPC (stdin/stdout/message passing) — no shared memory.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;code&gt;cluster&lt;/code&gt;&lt;/strong&gt; is built on top of &lt;code&gt;child_process&lt;/code&gt;, specifically for scaling &lt;em&gt;Node servers&lt;/em&gt; across multiple CPU cores. It forks multiple copies of your entire Node process, and the OS (or a Node-managed load balancer) distributes incoming connections across them. Great for "I have a web server and want to use all my CPU cores" — but each worker is a full separate process with its own memory, event loop, everything. It's about scaling &lt;strong&gt;throughput of independent requests&lt;/strong&gt;, not about parallelizing a single computation.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;code&gt;worker_threads&lt;/code&gt;&lt;/strong&gt; spawns actual OS-level &lt;em&gt;threads&lt;/em&gt; within the same process — lighter weight than a full process, and critically, capable of &lt;strong&gt;sharing memory&lt;/strong&gt; via &lt;code&gt;SharedArrayBuffer&lt;/code&gt;. Each worker gets its own V8 instance and its own event loop, so it's still not shared-everything like threads in languages such as Java or C++, but message passing is fast and structured data doesn't need full IPC serialization to a separate process. This is the right tool when you have &lt;strong&gt;one chunk of CPU-heavy work you want to offload without blocking the main thread&lt;/strong&gt; — image processing, cryptographic hashing, parsing a huge file, running a compute-heavy algorithm.&lt;/p&gt;

&lt;p&gt;Quick way to decide: scaling a whole server across cores → &lt;code&gt;cluster&lt;/code&gt;. Running an external program or needing hard process isolation → &lt;code&gt;child_process&lt;/code&gt;. Offloading one CPU-bound task from inside your existing app → &lt;code&gt;worker_threads&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;The rest of this post is about that last one.&lt;/p&gt;

&lt;h2&gt;
  
  
  Anatomy of a worker
&lt;/h2&gt;

&lt;p&gt;A worker is created from the main thread by pointing at a separate JS file:&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;// main.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;Worker&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;worker_threads&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;worker&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Worker&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./worker.js&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="nx"&gt;worker&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;on&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;message&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="nx"&gt;result&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="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="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Got result:&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="nx"&gt;worker&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;on&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;error&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="nx"&gt;err&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="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Worker error:&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="nx"&gt;worker&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;on&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;exit&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="nx"&gt;code&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;code&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;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`Worker stopped with exit code &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;code&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&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 javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// worker.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;parentPort&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;worker_threads&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;// do some CPU-heavy work here&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;heavyComputation&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="nx"&gt;parentPort&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;postMessage&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;result&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 key pieces:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;parentPort&lt;/code&gt;&lt;/strong&gt; — the worker's side of the communication channel back to whoever created it. &lt;code&gt;.postMessage()&lt;/code&gt; sends data out; listening on &lt;code&gt;parentPort.on('message', ...)&lt;/code&gt; receives data in.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;workerData&lt;/code&gt;&lt;/strong&gt; — lets you pass initial data into the worker at creation time, instead of messaging it in after startup:
&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="c1"&gt;// main.js&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;worker&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Worker&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./worker.js&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;workerData&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;n&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;40&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 javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// worker.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;workerData&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;parentPort&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;worker_threads&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;fibonacci&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;n&lt;/span&gt;&lt;span class="p"&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;n&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;n&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;fibonacci&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;n&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="o"&gt;+&lt;/span&gt; &lt;span class="nf"&gt;fibonacci&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;n&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nx"&gt;parentPort&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;postMessage&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;fibonacci&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;workerData&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;n&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Message passing between main thread and worker uses the &lt;strong&gt;structured clone algorithm&lt;/strong&gt; — the same mechanism &lt;code&gt;postMessage&lt;/code&gt; uses in browsers between windows/iframes. It can handle most JS values (objects, arrays, Maps, Sets, dates, even &lt;code&gt;ArrayBuffer&lt;/code&gt;s by transfer), but not everything — functions and certain non-serializable values can't cross the boundary. Each message is cloned by default, which has a real memory/CPU cost for large payloads — that's part of why &lt;code&gt;SharedArrayBuffer&lt;/code&gt; exists, more on that below.&lt;/p&gt;

&lt;h2&gt;
  
  
  Fixing the frozen server
&lt;/h2&gt;

&lt;p&gt;Let's rewrite the earlier example properly:&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;// main.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;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="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Worker&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;worker_threads&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;runFibWorker&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;n&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&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;resolve&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;reject&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;worker&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Worker&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./fib-worker.js&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;workerData&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;n&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
    &lt;span class="nx"&gt;worker&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;on&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;message&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nx"&gt;worker&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;on&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;error&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;reject&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nx"&gt;worker&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;on&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;exit&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="nx"&gt;code&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;code&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="nf"&gt;reject&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`Worker exited with code &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;code&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
    &lt;span class="p"&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;server&lt;/span&gt; &lt;span class="o"&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;/fib&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;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;runFibWorker&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;40&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="s2"&gt;`Result: &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;return&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;OK&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="nx"&gt;server&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;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// fib-worker.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;workerData&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;parentPort&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;worker_threads&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;fibonacci&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;n&lt;/span&gt;&lt;span class="p"&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;n&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;n&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;fibonacci&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;n&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="o"&gt;+&lt;/span&gt; &lt;span class="nf"&gt;fibonacci&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;n&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nx"&gt;parentPort&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;postMessage&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;fibonacci&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;workerData&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;n&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now hitting &lt;code&gt;/fib&lt;/code&gt; spins up a worker thread to do the computation, and the main thread's event loop stays completely free to keep serving other requests while it waits for the &lt;code&gt;message&lt;/code&gt; event. This is the actual fix — not a clever async trick, but real parallel execution on a separate thread.&lt;/p&gt;

&lt;h2&gt;
  
  
  Don't spin up a worker per request — use a pool
&lt;/h2&gt;

&lt;p&gt;The example above works, but spawning a brand-new &lt;code&gt;Worker&lt;/code&gt; (and its own V8 instance) for every single request is expensive — worker startup isn't free. In any real system, you want a &lt;strong&gt;worker pool&lt;/strong&gt;: a fixed set of long-lived workers that pick up jobs from a queue, so you pay the startup cost once and reuse threads across many tasks.&lt;/p&gt;

&lt;p&gt;Here's a reasonably complete pool implementation:&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;// worker-pool.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;Worker&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;worker_threads&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;os&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;os&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;WorkerPool&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;constructor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;workerScript&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;poolSize&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;cpus&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;workerScript&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;workerScript&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;poolSize&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;poolSize&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;workers&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[];&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;freeWorkers&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[];&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;taskQueue&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="nx"&gt;poolSize&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="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;_addWorker&lt;/span&gt;&lt;span class="p"&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;_addWorker&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;worker&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Worker&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;workerScript&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nx"&gt;worker&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;on&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;message&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="nx"&gt;result&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="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;resolve&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;worker&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;currentTask&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="nx"&gt;worker&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;currentTask&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="nf"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;_takeNextTask&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;worker&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;
    &lt;span class="nx"&gt;worker&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;on&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;error&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="nx"&gt;err&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="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;reject&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;worker&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;currentTask&lt;/span&gt; &lt;span class="o"&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;reject&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="nf"&gt;reject&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="c1"&gt;// Replace the crashed worker so the pool stays at full size&lt;/span&gt;
      &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;workers&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;workers&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;filter&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;w&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;w&lt;/span&gt; &lt;span class="o"&gt;!==&lt;/span&gt; &lt;span class="nx"&gt;worker&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;_addWorker&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;workers&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;worker&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;freeWorkers&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;worker&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="nf"&gt;_takeNextTask&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;worker&lt;/span&gt;&lt;span class="p"&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="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;taskQueue&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;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;freeWorkers&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;worker&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="k"&gt;return&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="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;reject&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;taskQueue&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;shift&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="nx"&gt;worker&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;currentTask&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;reject&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;
    &lt;span class="nx"&gt;worker&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;postMessage&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="nf"&gt;runTask&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&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;resolve&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;reject&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;freeWorker&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;freeWorkers&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;pop&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;freeWorker&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;freeWorker&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;currentTask&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;reject&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;
        &lt;span class="nx"&gt;freeWorker&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;postMessage&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;taskQueue&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;data&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;reject&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
      &lt;span class="p"&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="nf"&gt;destroy&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="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;workers&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;w&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;w&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;terminate&lt;/span&gt;&lt;span class="p"&gt;()));&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nx"&gt;module&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;exports&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;WorkerPool&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 javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// pool-worker.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;parentPort&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;worker_threads&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;fibonacci&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;n&lt;/span&gt;&lt;span class="p"&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;n&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;n&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;fibonacci&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;n&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="o"&gt;+&lt;/span&gt; &lt;span class="nf"&gt;fibonacci&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;n&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nx"&gt;parentPort&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;on&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;message&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="nx"&gt;n&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="nx"&gt;parentPort&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;postMessage&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;fibonacci&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;n&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 javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// main.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;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;WorkerPool&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;./worker-pool&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;pool&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;WorkerPool&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./pool-worker.js&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;server&lt;/span&gt; &lt;span class="o"&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;/fib&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;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;pool&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;runTask&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;40&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="s2"&gt;`Result: &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;return&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;OK&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="nx"&gt;server&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;Sizing the pool to &lt;code&gt;os.cpus().length&lt;/code&gt; is a sensible default — one worker per logical core, so you're not oversubscribing the CPU with more compute-bound threads than you have cores to run them on. This pattern (or a maintained library like &lt;code&gt;piscina&lt;/code&gt;, which does essentially this with more polish) is genuinely how you'd offload CPU work in production Node.&lt;/p&gt;

&lt;h2&gt;
  
  
  SharedArrayBuffer and Atomics — when message passing isn't enough
&lt;/h2&gt;

&lt;p&gt;By default, data sent between the main thread and a worker is &lt;strong&gt;cloned&lt;/strong&gt;. For most use cases that's fine, but for large datasets — a big typed array you want multiple workers reading and writing without copying gigabytes back and forth — cloning becomes the bottleneck itself.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;SharedArrayBuffer&lt;/code&gt; gives you a chunk of memory that's genuinely shared between threads — no cloning, both sides see the same bytes:&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;// main.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;Worker&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;worker_threads&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;sharedBuffer&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;SharedArrayBuffer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// 4 bytes = one Int32&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;sharedArray&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Int32Array&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;sharedBuffer&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;worker&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Worker&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./increment-worker.js&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;workerData&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;sharedBuffer&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="nx"&gt;worker&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;on&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;exit&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="o"&gt;=&amp;gt;&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="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Final value:&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;sharedArray&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="c1"&gt;// both threads touched the same memory&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 javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// increment-worker.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;workerData&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;parentPort&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;worker_threads&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;sharedArray&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Int32Array&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;workerData&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;sharedBuffer&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nx"&gt;Atomics&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;sharedArray&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;1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nx"&gt;parentPort&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;close&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Note the use of &lt;code&gt;Atomics.add&lt;/code&gt; rather than &lt;code&gt;sharedArray[0]++&lt;/code&gt;. This matters: when multiple threads can touch the same memory simultaneously, plain read-modify-write operations are subject to race conditions — two threads can both read the same old value before either writes back, and one increment gets silently lost. &lt;code&gt;Atomics&lt;/code&gt; provides operations (&lt;code&gt;add&lt;/code&gt;, &lt;code&gt;sub&lt;/code&gt;, &lt;code&gt;compareExchange&lt;/code&gt;, &lt;code&gt;load&lt;/code&gt;, &lt;code&gt;store&lt;/code&gt;, and more) that are guaranteed to be indivisible at the hardware level, so concurrent access doesn't corrupt the value. &lt;code&gt;Atomics.wait&lt;/code&gt; and &lt;code&gt;Atomics.notify&lt;/code&gt; go further, letting threads actually block and signal each other — a real synchronization primitive, not just safe arithmetic.&lt;/p&gt;

&lt;p&gt;This is a genuinely deep topic on its own — safe concurrent memory access is one of the harder problems in any multithreaded system, not a JS-specific quirk — so treat this section as "know it exists and roughly what it's for," not a complete guide. Most real workloads are well served by message passing through a pool; reach for &lt;code&gt;SharedArrayBuffer&lt;/code&gt; specifically when you've profiled and confirmed that cloning large data is the actual bottleneck.&lt;/p&gt;

&lt;h2&gt;
  
  
  When to actually reach for worker_threads
&lt;/h2&gt;

&lt;p&gt;Worth being honest about the tradeoffs before you reach for this in your own code:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Worker startup has real cost.&lt;/strong&gt; Spinning up a V8 instance per thread isn't free — this is exactly why pooling matters for anything beyond a one-off script.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Not everything benefits.&lt;/strong&gt; If your bottleneck is I/O (database calls, network requests, file reads), workers don't help — that's exactly what the async event loop from parts 1 and 2 already handles well, without the overhead of a thread.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Message passing has a cost too.&lt;/strong&gt; For small payloads it's negligible; for large ones, either restructure to send less data or use &lt;code&gt;SharedArrayBuffer&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Debugging is harder.&lt;/strong&gt; Errors in a worker don't naturally propagate the way synchronous exceptions do — you have to explicitly listen for &lt;code&gt;'error'&lt;/code&gt; events, and stack traces across threads are less convenient to work with.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The honest heuristic: profile first. If your server is slow because it's waiting on a database, adding worker threads won't fix anything — that's an I/O problem, and the event loop already handles it well. Worker threads earn their complexity specifically when you've identified genuine CPU-bound work — a synchronous computation heavy enough to visibly block the main thread — and optimizing the algorithm itself isn't enough.&lt;/p&gt;

&lt;h2&gt;
  
  
  Tying the series together
&lt;/h2&gt;

&lt;p&gt;Three parts, one throughline:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Part 1&lt;/strong&gt; gave you the spec-level model — stack, microtask queue, macrotask queue, and the rule that microtasks always drain first.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Part 2&lt;/strong&gt; showed that model isn't implemented identically everywhere — the browser interleaves it with rendering, Node runs it through libuv's ordered phases, and Node adds &lt;code&gt;process.nextTick()&lt;/code&gt; as a queue-jumper the browser doesn't have.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Part 3&lt;/strong&gt; showed the model's actual limit — a single thread, no matter how cleverly you schedule callbacks on it, can't parallelize genuine CPU-bound work. &lt;code&gt;worker_threads&lt;/code&gt; is Node's way out of that constraint.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Put together, this is really the full picture of "how does async JS work" — from the queue ordering that decides what runs next, to the runtime-specific machinery underneath it, to the point where you need real threads instead of clever scheduling. If you made it through all three, you're in a genuinely small group of JS developers who could actually explain &lt;em&gt;why&lt;/em&gt; &lt;code&gt;setImmediate&lt;/code&gt; and &lt;code&gt;setTimeout(fn, 0)&lt;/code&gt; race unpredictably at the top level of a script, or &lt;em&gt;why&lt;/em&gt; a recursive &lt;code&gt;.then()&lt;/code&gt; chain can freeze a browser tab without ever blocking the call stack.&lt;/p&gt;

&lt;p&gt;That's the kind of understanding that turns "the event loop is confusing" into "the event loop is just a queue, some phases, and a very specific set of rules about what runs first" — which, at the end of the day, it is.&lt;/p&gt;

</description>
      <category>node</category>
      <category>javascript</category>
      <category>backend</category>
      <category>performance</category>
    </item>
    <item>
      <title>Browser vs Node — Where the Event Loop Actually Diverges (Part 2/3)</title>
      <dc:creator>Aniket Misra</dc:creator>
      <pubDate>Tue, 04 Aug 2026 18:21:11 +0000</pubDate>
      <link>https://dev.to/aniket_misra_e47d1564ab7b/browser-vs-node-where-the-event-loop-actually-diverges-part-23-3j6c</link>
      <guid>https://dev.to/aniket_misra_e47d1564ab7b/browser-vs-node-where-the-event-loop-actually-diverges-part-23-3j6c</guid>
      <description>&lt;p&gt;In part 1, we built the shared mental model: call stack, microtask queue, macrotask queue, and the rule that microtasks fully drain before the next macrotask runs. That model is spec-level JavaScript behavior — but it's not the whole story once you actually run code.&lt;/p&gt;

&lt;p&gt;The event loop isn't part of the JS language spec. It's part of the &lt;strong&gt;host environment&lt;/strong&gt; — the browser or Node — and each one implements it differently around that shared core. This is the post most "event loop" explainers skip, because it means going past the diagram and into how each runtime is actually built.&lt;/p&gt;

&lt;h2&gt;
  
  
  The browser: event loop meets rendering
&lt;/h2&gt;

&lt;p&gt;In a browser, the event loop isn't just juggling callbacks — it's also responsible for keeping the page visually responsive. That means rendering has to get a turn too, and the browser has to decide &lt;em&gt;when&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;Here's the roughly accurate sequence per loop iteration:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Execute one macrotask (a click handler, a &lt;code&gt;setTimeout&lt;/code&gt; callback, a network event, whatever's next in the queue)&lt;/li&gt;
&lt;li&gt;Drain the entire microtask queue&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Maybe&lt;/strong&gt; render a frame — the browser doesn't render after every single task; it tries to hit ~60fps and will batch work between paints&lt;/li&gt;
&lt;li&gt;Go back to step 1&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The "maybe render" part is where two APIs come in that don't exist in Node at all:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;code&gt;requestAnimationFrame(callback)&lt;/code&gt;&lt;/strong&gt; — schedules a callback to run right before the next repaint. It's not a macrotask or microtask in the queue sense — it's tied directly to the rendering pipeline. Use it for anything visual (animations, DOM measurements) instead of &lt;code&gt;setTimeout&lt;/code&gt;, because it's synced to when the browser is actually about to paint, not an arbitrary delay.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;code&gt;requestIdleCallback(callback)&lt;/code&gt;&lt;/strong&gt; — schedules a callback to run when the browser is idle, after layout and paint, with a deadline. Meant for low-priority work you don't want competing with rendering — analytics, prefetching, non-urgent DOM updates.&lt;/p&gt;

&lt;p&gt;Here's the key interaction that's easy to miss: &lt;strong&gt;microtasks can starve rendering.&lt;/strong&gt; If a promise chain keeps queueing more microtasks, the browser can't get to the paint step, because microtasks always drain fully before rendering gets a turn. This is a real, debuggable performance bug — a runaway &lt;code&gt;.then()&lt;/code&gt; chain can visibly freeze a page even though "nothing is blocking the main thread" in the traditional sync-loop sense.&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="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;recursiveMicrotask&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&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;resolve&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;recursiveMicrotask&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="nf"&gt;recursiveMicrotask&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="c1"&gt;// Page becomes unresponsive — not because the stack is blocked,&lt;/span&gt;
&lt;span class="c1"&gt;// but because the microtask queue never empties long enough for a paint.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Compare that to a &lt;code&gt;setTimeout&lt;/code&gt;-based recursive loop — because each iteration is a separate macrotask, the browser gets a chance to render between them.&lt;/p&gt;

&lt;h2&gt;
  
  
  Node: no rendering, but a much more structured loop
&lt;/h2&gt;

&lt;p&gt;Node doesn't render anything, so it doesn't need the "maybe paint" logic. Instead, it's built on &lt;strong&gt;libuv&lt;/strong&gt;, a C library that gives Node its event loop, thread pool, and async I/O. libuv organizes the loop into distinct &lt;strong&gt;phases&lt;/strong&gt;, each with its own FIFO queue of callbacks. This is a meaningfully different shape from the browser's single task queue.&lt;/p&gt;

&lt;p&gt;The phases, in order, each loop tick:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;timers&lt;/strong&gt; — runs callbacks scheduled by &lt;code&gt;setTimeout&lt;/code&gt; / &lt;code&gt;setInterval&lt;/code&gt; whose threshold has elapsed&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;pending callbacks&lt;/strong&gt; — executes I/O callbacks deferred from the previous loop iteration (some system-level TCP errors, etc.)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;idle, prepare&lt;/strong&gt; — internal use only&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;poll&lt;/strong&gt; — the big one: retrieves new I/O events, executes I/O-related callbacks (almost everything — file reads, network requests). Node will block here waiting for new events if there's nothing else scheduled&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;check&lt;/strong&gt; — &lt;code&gt;setImmediate()&lt;/code&gt; callbacks run here, specifically &lt;em&gt;after&lt;/em&gt; poll&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;close callbacks&lt;/strong&gt; — e.g. &lt;code&gt;socket.on('close', ...)&lt;/code&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Then it loops back to timers.&lt;/p&gt;

&lt;p&gt;Between &lt;strong&gt;every single callback&lt;/strong&gt; — not just between phases, but between individual callbacks within a phase — Node drains the microtask queue. Same drain-fully rule as the browser, just applied at a finer grain because there's no rendering to interleave with.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;code&gt;process.nextTick()&lt;/code&gt; — Node's queue-jumper
&lt;/h2&gt;

&lt;p&gt;Node has a queue that doesn't exist in the browser at all: &lt;code&gt;process.nextTick()&lt;/code&gt;. Despite the name, it doesn't queue for "next tick" of the event loop — it runs &lt;strong&gt;before microtasks&lt;/strong&gt;, after the current operation finishes, no matter what.&lt;/p&gt;

&lt;p&gt;Priority order in Node, after any synchronous code completes:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;code&gt;process.nextTick()&lt;/code&gt; queue (fully drained)&lt;/li&gt;
&lt;li&gt;Promise microtask queue (fully drained)&lt;/li&gt;
&lt;li&gt;Next macrotask/phase callback
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nf"&gt;setTimeout&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;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="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;timeout&lt;/span&gt;&lt;span class="dl"&gt;'&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="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;nextTick&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;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="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;nextTick&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;));&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;resolve&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;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="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;promise&lt;/span&gt;&lt;span class="dl"&gt;'&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="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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Output: &lt;code&gt;sync&lt;/code&gt;, &lt;code&gt;nextTick&lt;/code&gt;, &lt;code&gt;promise&lt;/code&gt;, &lt;code&gt;timeout&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;nextTick&lt;/code&gt; beats the promise every time, because Node checks and drains the &lt;code&gt;nextTick&lt;/code&gt; queue first, and — same recursion risk as the microtask-starvation example above — a recursive &lt;code&gt;process.nextTick()&lt;/code&gt; call can starve I/O entirely, since Node won't proceed past it to the poll phase.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;code&gt;setImmediate()&lt;/code&gt; vs &lt;code&gt;setTimeout(fn, 0)&lt;/code&gt; — the ambiguous one
&lt;/h2&gt;

&lt;p&gt;This is the example that shows up in almost every Node interview, and the honest answer is: &lt;strong&gt;it depends on where you call it from.&lt;/strong&gt;&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="nf"&gt;setTimeout&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;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="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;timeout&lt;/span&gt;&lt;span class="dl"&gt;'&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="nf"&gt;setImmediate&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;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="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;immediate&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Run this at the &lt;strong&gt;top level&lt;/strong&gt; of a script, and the order is not guaranteed — it depends on process startup timing, specifically whether the timers phase's threshold has already elapsed by the time the loop starts. You'll see it flip between runs.&lt;/p&gt;

&lt;p&gt;But inside an I/O callback, the order is deterministic:&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;fs&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;fs&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="nx"&gt;fs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;readFile&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;__filename&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="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;setTimeout&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;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="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;timeout&lt;/span&gt;&lt;span class="dl"&gt;'&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="nf"&gt;setImmediate&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;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="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;immediate&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Output is always &lt;code&gt;immediate&lt;/code&gt;, then &lt;code&gt;timeout&lt;/code&gt;. Why? Because &lt;code&gt;fs.readFile&lt;/code&gt;'s callback runs in the &lt;strong&gt;poll&lt;/strong&gt; phase. From there, the loop moves to &lt;strong&gt;check&lt;/strong&gt; next — where &lt;code&gt;setImmediate&lt;/code&gt; lives — before it wraps back around to &lt;strong&gt;timers&lt;/strong&gt;. The phase order guarantees it here, where at the top level there's no such guarantee.&lt;/p&gt;

&lt;p&gt;This is a genuinely useful thing to internalize: &lt;code&gt;setImmediate&lt;/code&gt; means "run in the check phase, this loop iteration," while &lt;code&gt;setTimeout(fn, 0)&lt;/code&gt; means "run in the timers phase, next time the loop gets there" — and those are different guarantees depending on what phase you're currently in when you schedule them.&lt;/p&gt;

&lt;h2&gt;
  
  
  Side-by-side: browser vs Node
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Concept&lt;/th&gt;
&lt;th&gt;Browser&lt;/th&gt;
&lt;th&gt;Node&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Underlying engine&lt;/td&gt;
&lt;td&gt;V8 (Chrome), SpiderMonkey (Firefox), etc.&lt;/td&gt;
&lt;td&gt;V8 + libuv&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Queue structure&lt;/td&gt;
&lt;td&gt;Single task queue + microtask queue&lt;/td&gt;
&lt;td&gt;Multiple phase-specific queues (libuv) + microtask queue&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Rendering concern&lt;/td&gt;
&lt;td&gt;Yes — interleaved between tasks&lt;/td&gt;
&lt;td&gt;No rendering at all&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;setTimeout(fn, 0)&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Runs as next macrotask, after microtasks drain&lt;/td&gt;
&lt;td&gt;Runs in the timers phase, next time loop reaches it&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;setImmediate()&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Doesn't exist&lt;/td&gt;
&lt;td&gt;Runs in the check phase&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;process.nextTick()&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Doesn't exist&lt;/td&gt;
&lt;td&gt;Runs before microtasks, after current operation&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Idle/low-priority work&lt;/td&gt;
&lt;td&gt;&lt;code&gt;requestIdleCallback()&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;No direct equivalent — usually just &lt;code&gt;setImmediate()&lt;/code&gt; or offloading&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Animation timing&lt;/td&gt;
&lt;td&gt;&lt;code&gt;requestAnimationFrame()&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;No equivalent — no rendering to sync to&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;I/O model&lt;/td&gt;
&lt;td&gt;Web APIs (fetch, XHR, DOM events)&lt;/td&gt;
&lt;td&gt;libuv (thread pool for fs, async for network)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  What carries over, and what doesn't
&lt;/h2&gt;

&lt;p&gt;The stack/microtask/macrotask model from part 1 is real in both environments — that part's spec-driven and doesn't change. But the &lt;em&gt;shape&lt;/em&gt; of the macrotask side is genuinely different: the browser has one queue and a rendering step to juggle; Node has an ordered set of phases with distinct semantics per phase, plus &lt;code&gt;process.nextTick()&lt;/code&gt; sitting in front of everything.&lt;/p&gt;

&lt;p&gt;If you've been assuming "the event loop" is one universal thing you can reason about the same way in a React component and an Express handler, this is usually where that assumption breaks — and where subtle bugs (starved I/O from recursive &lt;code&gt;nextTick&lt;/code&gt;, or a &lt;code&gt;setTimeout&lt;/code&gt;-vs-&lt;code&gt;setImmediate&lt;/code&gt; race at startup) actually come from in production code.&lt;/p&gt;

&lt;h2&gt;
  
  
  Coming up next
&lt;/h2&gt;

&lt;p&gt;Both of these models assume your callbacks are fast. But what happens when you genuinely have CPU-heavy work — image processing, large computations, parsing — that can't be broken into tiny async chunks? No amount of clever queue ordering saves you if a single synchronous function blocks the thread for 500ms.&lt;/p&gt;

&lt;p&gt;Part 3 covers Node's answer to that: &lt;code&gt;worker_threads&lt;/code&gt; — real OS-level threads, how to actually use them, and when reaching for a worker beats just optimizing your algorithm.&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>node</category>
      <category>webdev</category>
      <category>backend</category>
    </item>
    <item>
      <title>The JS Event Loop — Core Mental Model (Part 1/3)</title>
      <dc:creator>Aniket Misra</dc:creator>
      <pubDate>Tue, 04 Aug 2026 18:13:49 +0000</pubDate>
      <link>https://dev.to/aniket_misra_e47d1564ab7b/the-js-event-loop-core-mental-model-part-13-289i</link>
      <guid>https://dev.to/aniket_misra_e47d1564ab7b/the-js-event-loop-core-mental-model-part-13-289i</guid>
      <description>&lt;p&gt;JavaScript is single-threaded. One call stack, one thing happening at a time. And yet your code fetches data, sets timers, listens for clicks, and handles I/O — all without blocking. How?&lt;/p&gt;

&lt;p&gt;The answer is the &lt;strong&gt;event loop&lt;/strong&gt;, and it's one of those concepts every JS developer &lt;em&gt;thinks&lt;/em&gt; they understand until someone asks them to predict the output of five nested &lt;code&gt;setTimeout&lt;/code&gt; and &lt;code&gt;Promise&lt;/code&gt; calls.&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;The core event loop model&lt;/strong&gt; (this post)&lt;/li&gt;
&lt;li&gt;Where Node and the browser actually diverge&lt;/li&gt;
&lt;li&gt;Escaping the event loop with &lt;code&gt;worker_threads&lt;/code&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Let's build the mental model properly.&lt;/p&gt;

&lt;h2&gt;
  
  
  JS is single-threaded — so what's actually running your async code?
&lt;/h2&gt;

&lt;p&gt;The JS engine (V8, SpiderMonkey, etc.) only executes one thing at a time on the &lt;strong&gt;call stack&lt;/strong&gt;. There's no multithreading inside the engine itself.&lt;/p&gt;

&lt;p&gt;But the &lt;em&gt;runtime&lt;/em&gt; around the engine — the browser or Node — provides extra machinery: Web APIs in the browser (timers, DOM events, fetch), or C++ APIs via libuv in Node (timers, file I/O, network). These run outside the JS thread. When they finish, they don't just barge into your running code — they queue up a callback to be run later.&lt;/p&gt;

&lt;p&gt;That queueing and "run later" part is the event loop's job.&lt;/p&gt;

&lt;h2&gt;
  
  
  The three pieces: stack, queue, loop
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Call stack&lt;/strong&gt; — where synchronous code executes, frame by frame. If a function calls another function, it stacks. When a function returns, it pops.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Queue(s)&lt;/strong&gt; — where callbacks wait after some async operation completes. There isn't just one queue (more on that in a second).&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Event loop&lt;/strong&gt; — a simple, repeating check: &lt;em&gt;"Is the call stack empty? If yes, take the next thing from a queue and push it onto the stack."&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;That's genuinely most of it. The complexity comes from &lt;strong&gt;which queue goes first&lt;/strong&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Macrotasks vs microtasks
&lt;/h2&gt;

&lt;p&gt;This is the part that trips people up, so let's be precise.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Macrotasks&lt;/strong&gt; (aka "tasks") include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;setTimeout&lt;/code&gt; / &lt;code&gt;setInterval&lt;/code&gt; callbacks&lt;/li&gt;
&lt;li&gt;I/O callbacks&lt;/li&gt;
&lt;li&gt;UI rendering-related callbacks (browser)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Microtasks&lt;/strong&gt; include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;Promise.then&lt;/code&gt; / &lt;code&gt;.catch&lt;/code&gt; / &lt;code&gt;.finally&lt;/code&gt; callbacks&lt;/li&gt;
&lt;li&gt;&lt;code&gt;queueMicrotask()&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;async/await&lt;/code&gt; continuations (they're sugar over promises)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The rule that matters: &lt;strong&gt;after every single macrotask, the event loop fully drains the microtask queue before it does anything else&lt;/strong&gt; — including before rendering a frame or running the next macrotask.&lt;/p&gt;

&lt;p&gt;Not "checks it once." Drains it completely. If a microtask queues another microtask, that runs too, before moving on.&lt;/p&gt;

&lt;h2&gt;
  
  
  The classic gotcha, explained properly
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&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="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;1&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="nf"&gt;setTimeout&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;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="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;2&lt;/span&gt;&lt;span class="dl"&gt;'&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="nb"&gt;Promise&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;resolve&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;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="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;3&lt;/span&gt;&lt;span class="dl"&gt;'&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="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;4&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Try to predict the order before reading on.&lt;/p&gt;

&lt;p&gt;Here's what happens, step by step:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;code&gt;console.log('1')&lt;/code&gt; runs synchronously → prints &lt;code&gt;1&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;setTimeout(...)&lt;/code&gt; hands its callback off to the runtime's timer API and registers a &lt;strong&gt;macrotask&lt;/strong&gt; for later — even with a &lt;code&gt;0ms&lt;/code&gt; delay, it doesn't run immediately&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;Promise.resolve().then(...)&lt;/code&gt; queues a &lt;strong&gt;microtask&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;console.log('4')&lt;/code&gt; runs synchronously → prints &lt;code&gt;4&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Call stack is now empty. Event loop checks the &lt;strong&gt;microtask queue first&lt;/strong&gt; → runs it → prints &lt;code&gt;3&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Microtask queue is empty. Event loop moves to the &lt;strong&gt;macrotask queue&lt;/strong&gt; → runs the timeout callback → prints &lt;code&gt;2&lt;/code&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Output: &lt;code&gt;1, 4, 3, 2&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;The part people get wrong is assuming &lt;code&gt;setTimeout(fn, 0)&lt;/code&gt; means "run next." It doesn't mean "run next" — it means "run next &lt;em&gt;macrotask&lt;/em&gt; turn," and microtasks always cut the line first.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why this ordering exists at all
&lt;/h2&gt;

&lt;p&gt;It's not arbitrary. Microtasks are meant for &lt;strong&gt;finishing up work that's already in flight&lt;/strong&gt; — resolving a promise chain, reacting to something that just happened — before the system moves on to genuinely new, separately-scheduled work like a timer firing or an I/O event arriving. It keeps related async logic coherent and predictable, rather than letting it get interleaved with unrelated queued tasks.&lt;/p&gt;

&lt;h2&gt;
  
  
  Quick check — predict the output
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&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="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;start&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="nf"&gt;setTimeout&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;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="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;timeout&lt;/span&gt;&lt;span class="dl"&gt;'&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="nb"&gt;Promise&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;resolve&lt;/span&gt;&lt;span class="p"&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;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="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;promise 1&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;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;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="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;promise 2&lt;/span&gt;&lt;span class="dl"&gt;'&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="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;end&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Drop your answer in the comments before scrolling through devtools to check — this is exactly the kind of ordering that gets asked in interviews, and exactly the kind of bug that shows up in real async code when you assume timers run "immediately."&lt;/p&gt;

&lt;p&gt;Answer&lt;/p&gt;

&lt;p&gt;&lt;code&gt;start&lt;/code&gt;, &lt;code&gt;end&lt;/code&gt;, &lt;code&gt;promise 1&lt;/code&gt;, &lt;code&gt;promise 2&lt;/code&gt;, &lt;code&gt;timeout&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Both &lt;code&gt;.then()&lt;/code&gt; callbacks are microtasks and both drain before the macrotask queue is touched — even though the second &lt;code&gt;.then()&lt;/code&gt; is only &lt;em&gt;queued&lt;/em&gt; once the first one runs.&lt;/p&gt;

&lt;h2&gt;
  
  
  What's next
&lt;/h2&gt;

&lt;p&gt;This model — stack, microtask queue, macrotask queue, drain-before-next-task — is the &lt;strong&gt;shared spec-level behavior&lt;/strong&gt; both browsers and Node implement. But they don't implement the &lt;em&gt;runtime&lt;/em&gt; around it the same way.&lt;/p&gt;

&lt;p&gt;Browsers have to interleave this with rendering. Node runs on libuv with distinct phases (timers, I/O, &lt;code&gt;setImmediate&lt;/code&gt;, close callbacks) and has its own microtask-like queue via &lt;code&gt;process.nextTick()&lt;/code&gt; that jumps the line even ahead of promises.&lt;/p&gt;

&lt;p&gt;That's where things get genuinely different — and where most "event loop" explanations stop short. Part 2 goes there.&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>webdev</category>
      <category>node</category>
      <category>beginners</category>
    </item>
    <item>
      <title>Before Solana Went Native: What the EVM Actually Is (And Why It Was Built to Be Slow)</title>
      <dc:creator>Aniket Misra</dc:creator>
      <pubDate>Mon, 13 Jul 2026 18:04:17 +0000</pubDate>
      <link>https://dev.to/aniket_misra_e47d1564ab7b/before-solana-went-native-what-the-evm-actually-is-and-why-it-was-built-to-be-slow-14h7</link>
      <guid>https://dev.to/aniket_misra_e47d1564ab7b/before-solana-went-native-what-the-evm-actually-is-and-why-it-was-built-to-be-slow-14h7</guid>
      <description>&lt;p&gt;To understand why Solana's decision to repurpose BPF was radical, you first need to understand what it was radical &lt;em&gt;against&lt;/em&gt;. That's the Ethereum Virtual Machine — the thing every other "VM for smart contracts" design, Solana included, is implicitly arguing with.&lt;/p&gt;

&lt;p&gt;The EVM isn't slow because Ethereum's engineers were careless. It's slow because of a set of design choices that made total sense in 2014, when the problem being solved wasn't "how do we get 50,000 TPS" — it was "how do we get a global network of mutually distrusting strangers to agree on the exact same computation, byte for byte, forever." Every property that makes the EVM feel heavy today is downstream of that one requirement.&lt;/p&gt;

&lt;p&gt;This is the prequel to a piece I wrote on how Solana re-engineered a Linux kernel packet filter into its execution layer. Before we get to what Solana did differently, here's what it was different &lt;em&gt;from&lt;/em&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  1. A Stack Machine, Not a Register Machine
&lt;/h2&gt;

&lt;p&gt;The EVM is a &lt;strong&gt;256-bit stack-based virtual machine&lt;/strong&gt;. There are no general-purpose registers. Every operation — arithmetic, comparisons, memory access — pushes and pops values from a stack, one instruction at a time.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight nasm"&gt;&lt;code&gt;&lt;span class="nf"&gt;PUSH1&lt;/span&gt; &lt;span class="mh"&gt;0x05&lt;/span&gt;
&lt;span class="nf"&gt;PUSH1&lt;/span&gt; &lt;span class="mh"&gt;0x03&lt;/span&gt;
&lt;span class="nf"&gt;ADD&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That's the entire bytecode for "5 + 3." No register allocation, no scheduling — the EVM interprets it top to bottom, exactly as written. This is also why Solidity compiles down to something conceptually close to this, opcode by opcode, rather than to a register-mapped instruction set the way a Rust program compiling to BPF does.&lt;/p&gt;

&lt;p&gt;The 256-bit word size isn't an accident either — it matches the output width of Keccak-256, the hash function baked into almost everything Ethereum does (addresses, storage slots, opcodes like &lt;code&gt;SHA3&lt;/code&gt;). The VM's fundamental data type was chosen to fit the cryptography, not the hardware.&lt;/p&gt;

&lt;p&gt;Compare that to a register machine like BPF or SBF, where the instruction set is designed to map closely to what a real CPU already does. The EVM was never trying to be fast on real silicon. It was trying to be &lt;em&gt;unambiguous&lt;/em&gt; — every implementation, on every machine, computing the exact same stack transitions.&lt;/p&gt;




&lt;h2&gt;
  
  
  2. Interpreted, All the Way Down
&lt;/h2&gt;

&lt;p&gt;There's no JIT. No AOT compilation to native code. Every EVM opcode, on every node, for every transaction, gets interpreted at runtime, instruction by instruction, by whatever client software that node happens to run (Geth, Nethermind, Besu — doesn't matter, they all have to agree).&lt;/p&gt;

&lt;p&gt;This is a deliberate constraint, not an oversight. If clients were free to JIT-compile bytecode to native machine code, you'd be trusting each client's compiler to preserve &lt;em&gt;exact&lt;/em&gt; semantics across compilation — including edge cases like integer overflow behavior and gas accounting quirks. One divergent optimization and the network forks. Interpretation is slow, but it's slow in a way that's trivially auditable: the reference behavior &lt;em&gt;is&lt;/em&gt; the implementation.&lt;/p&gt;

&lt;p&gt;Some newer EVM implementations do experiment with JIT compilation for performance, but the base protocol was never designed assuming it — correctness came first, speed was whatever was left over.&lt;/p&gt;




&lt;h2&gt;
  
  
  3. Gas: Metering Before Execution, Not Verification Before Execution
&lt;/h2&gt;

&lt;p&gt;The EVM has no static verifier checking that your bytecode terminates before it runs — there's no equivalent of eBPF's compile-time proof-of-termination. Instead, every single opcode has a fixed gas cost, charged as execution proceeds. Run out of gas, execution halts immediately and any state changes revert.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;function withdraw(uint amount) public {
    require(amount &amp;lt;= balances[msg.sender], "insufficient balance");
    balances[msg.sender] -= amount;
    payable(msg.sender).transfer(amount);
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Every line here costs gas — &lt;code&gt;SLOAD&lt;/code&gt; to read &lt;code&gt;balances[msg.sender]&lt;/code&gt;, &lt;code&gt;SSTORE&lt;/code&gt; to write it back, &lt;code&gt;CALL&lt;/code&gt; to send funds. The sender pre-pays an upper bound before the transaction even starts, and unused gas gets refunded. This is a fundamentally different safety model than a verifier: instead of proving a program &lt;em&gt;can't&lt;/em&gt; misbehave, you make misbehaving economically self-limiting. An infinite loop doesn't hang the network — it just burns through the caller's gas and reverts, at their expense.&lt;/p&gt;




&lt;h2&gt;
  
  
  4. Account-Based State and Why Everything Runs in Order
&lt;/h2&gt;

&lt;p&gt;Ethereum's state is a giant key-value mapping — accounts to balances, contract storage slots to values — represented as a Merkle Patricia Trie so any node can cryptographically prove the current state root. Crucially, a transaction doesn't declare up front which storage slots it's going to touch. It just runs, and reads/writes whatever it wants as it goes, including calling into other contracts that touch state you couldn't have predicted ahead of time.&lt;/p&gt;

&lt;p&gt;That's the detail that quietly determines Ethereum's entire concurrency story. If you don't know in advance what a transaction will touch, you can't safely run two transactions at once without risking a race on shared state. So the EVM, as a base protocol, executes transactions &lt;strong&gt;strictly sequentially&lt;/strong&gt;, one at a time, in block order. Parallel execution research exists (both inside and outside core Ethereum client teams), but it's an optimization bolted on after the fact, not a property the VM was built around.&lt;/p&gt;

&lt;p&gt;This is precisely the constraint Solana's Sealevel runtime sidesteps — by &lt;em&gt;requiring&lt;/em&gt; transactions to declare their account access lists upfront, Solana's runtime can prove non-overlap before execution and schedule accordingly. That's not a coincidence; it's a direct response to this exact bottleneck.&lt;/p&gt;




&lt;h2&gt;
  
  
  Why It's Built This Way
&lt;/h2&gt;

&lt;p&gt;None of this is Ethereum "doing it wrong." A stack machine with no JIT, gas-metered instead of statically verified, sequential by default — every one of these was the correct trade-off for a network whose founding problem was trustless consensus among strangers, not raw throughput. Determinism and auditability were the product. Speed was never the spec.&lt;/p&gt;

&lt;p&gt;That's exactly the gap Solana's architects looked at and decided to close from a completely different direction — not by making a better stack machine, but by throwing the stack-machine model out and grabbing a register-based, hardware-native VM that Linux had already spent two decades optimizing. What that actually involved — stripping the kernel verifier, zero-copy account access, AOT compilation to native code, and the account-declaration trick that unlocks parallelism — is the subject of the piece this one precedes.&lt;/p&gt;

&lt;p&gt;If you haven't read it yet: &lt;a href="https://dev.to/aniket_misra_e47d1564ab7b/from-packet-filter-to-high-performance-execution-layer-how-solana-re-engineered-bpf-214i"&gt;From Packet Filter to High-Performance Execution Layer: How Solana Re-Engineered BPF&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>architecture</category>
      <category>blockchain</category>
      <category>ethereum</category>
      <category>performance</category>
    </item>
    <item>
      <title>Kill the Server: Why Holepunch Threw Away Node.js and Built 'Bare'</title>
      <dc:creator>Aniket Misra</dc:creator>
      <pubDate>Sat, 11 Jul 2026 03:07:00 +0000</pubDate>
      <link>https://dev.to/aniket_misra_e47d1564ab7b/kill-the-server-why-holepunch-threw-away-nodejs-and-built-bare-3gdi</link>
      <guid>https://dev.to/aniket_misra_e47d1564ab7b/kill-the-server-why-holepunch-threw-away-nodejs-and-built-bare-3gdi</guid>
      <description>&lt;p&gt;When the Holepunch team set out to build Pear—a decentralized, peer-to-peer application runtime—they started with the obvious choice: Node.js. &lt;/p&gt;

&lt;p&gt;Node is the undisputed king of JavaScript outside the browser. It has a massive ecosystem, a battle-tested asynchronous event loop (&lt;code&gt;libuv&lt;/code&gt;), and the raw execution speed of Google's V8 engine. It seemed like the perfect foundation for a P2P stack.&lt;/p&gt;

&lt;p&gt;But as they dug deeper into cross-platform routing, NAT traversal, and mobile embedding, they hit a fundamental architectural roadblock: &lt;strong&gt;Node.js makes too many assumptions, and the biggest assumption it makes is that you are running a server.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Node was built for the data center. It carries decades of legacy APIs (&lt;code&gt;http&lt;/code&gt;, &lt;code&gt;net&lt;/code&gt;, &lt;code&gt;tls&lt;/code&gt;) that are tightly coupled to centralized, client-server web architecture. When you want to build a purely peer-to-peer, serverless network where devices connect directly via a Distributed Hash Table (DHT), all of that built-in Node bloat becomes dead weight.&lt;/p&gt;

&lt;p&gt;So, they did what any obsessive systems engineering team does. They stripped Node down to its studs, threw away the bloated standard library, and built &lt;strong&gt;Bare&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Here is a technical look at the Bare runtime, and why throwing away Node’s HTTP assumptions is the key to true P2P applications.&lt;/p&gt;




&lt;h2&gt;
  
  
  1. Deconstructing the Runtime: What is Bare?
&lt;/h2&gt;

&lt;p&gt;At its core, Bare is a minimalist JavaScript runtime designed specifically for desktop, mobile, and IoT embedding. &lt;/p&gt;

&lt;p&gt;It keeps the best parts of Node's foundational architecture but aggressively decouples the JavaScript engine from the system APIs.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[ Traditional Node.js Stack ]        [ The Bare Runtime Stack ]
┌─────────────────────────┐          ┌─────────────────────────┐
│     User Application    │          │     User Application    │
├─────────────────────────┤          ├─────────────────────────┤
│ Node Standard Library   │          │     Userland Modules    │
│ (http, fs, net, crypto) │          │ (HyperDHT, Hyperdrive)  │
├─────────────────────────┤          ├─────────────────────────┤
│    Node C++ Bindings    │          │           Bare          │
├────────────┬────────────┤          ├────────────┬────────────┤
│     V8     │   libuv    │          │    libjs   │   libuv    │
└────────────┴────────────┘          ├────────────┴────────────┤
                                     │V8/ QuickJS / JerryScript│
                                     └─────────────────────────┘
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Notice the key difference at the bottom of the stack: libjs.&lt;/p&gt;

&lt;p&gt;Node is rigidly bound to Google’s V8 engine. Bare abstracts the JavaScript engine behind a C-API wrapper called libjs. This is a massive systems-level advantage. While Bare runs V8 by default for desktop performance, libjs allows developers to swap out the engine entirely. If you are deploying a P2P application to a highly constrained LTE router or a microcontroller, you can swap V8 for lightweight engines like QuickJS or JerryScript without changing the core runtime architecture.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. The Missing Standard Library (A Feature, Not a Bug)
&lt;/h3&gt;

&lt;p&gt;If you install Bare and try to spin up a quick web server, it will fail:&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;// This works in Node. It fails in Bare.&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;http&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; 
&lt;span class="c1"&gt;// Error: Cannot find module 'http'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Bare intentionally ships with almost nothing. There is no http. There is no net. There is no crypto.&lt;/p&gt;

&lt;p&gt;Why? Because in a true peer-to-peer architecture, standard HTTP is an anti-pattern. If you rely on http, you are relying on DNS routing, centralized Certificate Authorities (TLS), and exposed public IP addresses.&lt;/p&gt;

&lt;p&gt;Instead of forcing a heavy standard library into the binary, Bare leaves feature implementation entirely to userland modules. The runtime provides only three core primitives:&lt;/p&gt;

&lt;p&gt;1.A module system (with bidirectional CJS and ESM interoperability).  &lt;/p&gt;

&lt;p&gt;2.A native addon system (for linking low-level C/C++ libraries).  &lt;/p&gt;

&lt;p&gt;3.Lightweight threads (with SharedArrayBuffer support).&lt;/p&gt;

&lt;p&gt;Everything else is imported a-la-carte. When you want to build a network connection in Bare, you don't use http. You use Holepunch's hyperdht, utilizing cryptographic keys instead of IPs.&lt;/p&gt;

&lt;h3&gt;
  
  
  3.Bare-Metal Embedding (Desktop to Mobile)
&lt;/h3&gt;

&lt;p&gt;Node is notoriously difficult to embed cleanly into mobile applications. If you want to run a Node instance inside an iOS app, you end up wrestling with massive binaries, battery drain, and messy IPC (Inter-Process Communication) bridges.&lt;/p&gt;

&lt;p&gt;Because Bare shed the standard library, its memory footprint is drastically reduced. It treats mobile as a first-class citizen.  &lt;/p&gt;

&lt;p&gt;Through Bare Kit, developers can spin up "worklets"—isolated Bare threads running directly inside native mobile frameworks (SwiftUI for iOS, or Android Services).&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;// Spawning a Bare worklet for background P2P sync&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Worklet&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;bare-kit&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;syncThread&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Worklet&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/hyperdrive-sync.js&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="nx"&gt;syncThread&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;on&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;message&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="nx"&gt;msg&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="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="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Mobile UI received state update from P2P swarm:&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;msg&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;

&lt;span class="nx"&gt;syncThread&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;postMessage&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;command&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;START_SYNC&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This allows a React Native or Swift frontend to offload all the heavy lifting—DHT routing, UDP hole punching, and data replication—to a highly efficient, native background thread that won't freeze the mobile UI.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Takeaway: Stop Building Servers
&lt;/h3&gt;

&lt;p&gt;When you look at Bare, you realize that the Node.js architecture we’ve been using for 15 years has subtly brainwashed us. We assume that writing backend JavaScript inherently means writing server logic.Bare proves that JavaScript can be used for something far more resilient. By stripping away the bloated legacy of the Web2 data center, Holepunch has created a runtime that actually belongs on the edge. It forces you to stop thinking about endpoints and status codes, and start thinking about swarms, peers, and cryptographic tunnels.  If you want to build systems that governments can't block and cloud providers can't crash, you have to kill the server. Bare is the runtime designed to do exactly that.&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>node</category>
      <category>bare</category>
      <category>holepunch</category>
    </item>
    <item>
      <title>The Dark Art of UDP Hole Punching: How to Build a Serverless Web</title>
      <dc:creator>Aniket Misra</dc:creator>
      <pubDate>Fri, 10 Jul 2026 19:57:35 +0000</pubDate>
      <link>https://dev.to/aniket_misra_e47d1564ab7b/the-dark-art-of-udp-hole-punching-how-to-build-a-serverless-web-1p7d</link>
      <guid>https://dev.to/aniket_misra_e47d1564ab7b/the-dark-art-of-udp-hole-punching-how-to-build-a-serverless-web-1p7d</guid>
      <description>&lt;p&gt;If you want to build a truly decentralized application—one that doesn't rely on AWS, Vercel, or a centralized RPC node—you immediately run into a brick wall of network physics. &lt;/p&gt;

&lt;p&gt;You want User A to talk directly to User B. &lt;br&gt;
The problem? Neither of them has a public IP address.&lt;/p&gt;

&lt;p&gt;Because we ran out of IPv4 addresses decades ago, ISPs placed almost every consumer device on earth behind a &lt;strong&gt;NAT (Network Address Translation)&lt;/strong&gt; router. NAT is a one-way mirror. You can send outbound requests to a public server, and the router will allow the response back in. But if an external device tries to initiate a connection with you, the NAT drops the packet immediately. It assumes it is hostile.&lt;/p&gt;

&lt;p&gt;This single piece of hardware killed the peer-to-peer internet. &lt;/p&gt;

&lt;p&gt;To build a sovereign, serverless application layer (like what Holepunch and Pear are doing), you have to bypass the NAT. You have to trick the router into letting inbound traffic through. This technique is called &lt;strong&gt;UDP Hole Punching&lt;/strong&gt;. &lt;/p&gt;

&lt;p&gt;Here is the architectural deep dive into how it works, and how modern cryptographic routing makes it scalable.&lt;/p&gt;


&lt;h2&gt;
  
  
  1. The Mechanics of the "Hole Punch"
&lt;/h2&gt;

&lt;p&gt;Unlike TCP, which requires a rigid 3-way handshake, &lt;strong&gt;UDP is connectionless&lt;/strong&gt;. It just fires raw datagrams into the void.&lt;/p&gt;

&lt;p&gt;When your laptop sends a UDP packet to an external server, your NAT router intercepts it, temporarily maps your local IP/port to its public IP/port, and adds a record to its &lt;strong&gt;State Table&lt;/strong&gt;. For the next 30 to 60 seconds, it leaves a "hole" open. If any UDP packet hits that specific public port, the NAT assumes it is a valid response and forwards it to your laptop.&lt;/p&gt;

&lt;p&gt;If Alice and Bob are both behind strict NATs, they cannot ping each other. But if they coordinate, they can exploit the state table.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;The Signaling Phase:&lt;/strong&gt; Alice and Bob both connect to a third-party relay to discover their own respective public IP addresses and ports.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The Simultaneous Strike:&lt;/strong&gt; Alice fires a UDP packet directly at Bob's public IP. Bob fires a UDP packet directly at Alice's public IP.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The Rejection:&lt;/strong&gt; Alice's first packet hits Bob's router and gets instantly dropped, because Bob's router hasn't opened a hole yet.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The Breakthrough:&lt;/strong&gt; But when Alice fired that packet, &lt;em&gt;her&lt;/em&gt; router opened a hole, expecting a response from Bob's IP. A millisecond later, Bob's packet arrives at Alice's router. Because the IP and port match the state table, the router lets it through. &lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The hole is punched. Alice and Bob now have a direct, peer-to-peer data stream.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[Alice's Laptop] ──► (Local Port 3000)
       │
 [Alice's NAT] ────► Opens Hole: Public IP A, Port 50000 
       │ 
       ▼ (Direct UDP Stream) ▲
       │                     │
 [Bob's NAT] ◄─────► Opens Hole: Public IP B, Port 60000
       │
[Bob's Laptop] ◄─── (Local Port 4000)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  2. The Holepunch Architecture: Cryptographic Routing
&lt;/h3&gt;

&lt;p&gt;In traditional WebRTC architecture, the "Signaling Phase" requires centralized infrastructure: &lt;strong&gt;STUN&lt;/strong&gt; servers (to find your public IP) and &lt;strong&gt;TURN&lt;/strong&gt; servers (to relay traffic if hole punching fails).  If you use STUN/TURN, you are back to relying on centralized cloud providers.The brilliance of the &lt;strong&gt;Holepunch&lt;/strong&gt; stack (and its underlying engine, Bare) is that it throws out STUN and TURN entirely. Instead, it uses &lt;strong&gt;HyperDHT&lt;/strong&gt;, a Kademlia-based Distributed Hash Table.  In this architecture, your public cryptographic key is your IP address.&lt;/p&gt;

&lt;p&gt;1.When Alice boots her application, she joins the DHT. The decentralized nodes in the DHT naturally observe her public IP and port, effectively doing the job of a STUN server without corporate ownership.&lt;br&gt;&lt;br&gt;
2.She announces her 32-byte public key (ed25519) to the swarm.&lt;br&gt;
3.When Bob wants to connect, he doesn't query a DNS server. He searches the DHT for Alice's public key.&lt;br&gt;
4.The DHT nodes coordinate the UDP hole punch. Once the connection is established, Alice and Bob perform a Noise IK handshake to generate a direct, end-to-end encrypted tunnel.&lt;br&gt;&lt;br&gt;
&lt;a href="//hypercore-protocol.github.io"&gt;Visit documentation&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  3. The Code: Bare-Metal P2P
&lt;/h3&gt;

&lt;p&gt;Because Holepunch uses the Bare runtime (stripping away Node.js's heavy HTTP server legacy), establishing this encrypted, serverless connection takes mere lines of code.&lt;/p&gt;

&lt;p&gt;Here is what establishing a serverless, hole-punched P2P connection looks like using hyperdht:&lt;br&gt;
&lt;strong&gt;Alice (The Target):&lt;/strong&gt;&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="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;DHT&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;hyperdht&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;node&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;DHT&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;keyPair&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;DHT&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;keyPair&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="c1"&gt;// Cryptographic identity&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;server&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;node&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="nx"&gt;socket&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&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="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Direct encrypted P2P stream established!&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

  &lt;span class="c1"&gt;// The socket is a standard duplex stream. &lt;/span&gt;
  &lt;span class="c1"&gt;// No server required.&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;stdin&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;pipe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;socket&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;pipe&lt;/span&gt;&lt;span class="p"&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;stdout&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="nx"&gt;server&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="nx"&gt;keyPair&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="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Listening on Public Key:&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;keyPair&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;publicKey&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Bob (The Dialer):&lt;/strong&gt;&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="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;DHT&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;hyperdht&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;node&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;DHT&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;alicePubKey&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;Buffer&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="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;&amp;lt;ALICE_PUBLIC_KEY_HEX&amp;gt;&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;hex&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;// The DHT locates Alice, orchestrates the UDP hole punch, &lt;/span&gt;
&lt;span class="c1"&gt;// and establishes the Noise IK encrypted tunnel natively.&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;socket&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;node&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;connect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;alicePubKey&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="nx"&gt;socket&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;on&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;open&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="o"&gt;=&amp;gt;&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="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Punched through NAT. Connected to Alice.&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="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;stdin&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;pipe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;socket&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;pipe&lt;/span&gt;&lt;span class="p"&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;stdout&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  The Unstoppable Web
&lt;/h3&gt;

&lt;p&gt;By utilizing UDP hole punching and a cryptographic DHT, you remove the ultimate single point of failure in modern architecture: the data center.&lt;/p&gt;

&lt;p&gt;You cannot DDoS a network where every user is dynamically routing traffic. You cannot de-platform an application that has no static IP to block. When we talk about true decentralization, it isn't just about putting a financial ledger on a blockchain; it is about reclaiming the physical routing layer of the internet.&lt;/p&gt;

</description>
      <category>web3</category>
      <category>p2p</category>
      <category>networking</category>
      <category>holepunch</category>
    </item>
    <item>
      <title>The Tether Paradox: Shitty ERC-20s, OpenZeppelin, and the Unstoppable Web</title>
      <dc:creator>Aniket Misra</dc:creator>
      <pubDate>Fri, 10 Jul 2026 18:24:31 +0000</pubDate>
      <link>https://dev.to/aniket_misra_e47d1564ab7b/the-tether-paradox-shitty-erc-20s-openzeppelin-and-the-unstoppable-web-2e5o</link>
      <guid>https://dev.to/aniket_misra_e47d1564ab7b/the-tether-paradox-shitty-erc-20s-openzeppelin-and-the-unstoppable-web-2e5o</guid>
      <description>&lt;p&gt;I have a confession to make. When I first saw that Tether—the behemoth behind the $110 billion USDT stablecoin—was the primary financial backer of Holepunch, Keet, and the Bare JavaScript runtime, my brain short-circuited. &lt;/p&gt;

&lt;p&gt;I struggled with the cognitive dissonance. Why? Because if you have ever written a smart contract that interacts with USDT on Ethereum Mainnet, you know it is an absolute nightmare. &lt;/p&gt;

&lt;p&gt;Before we can talk about Tether’s brilliant vision for a decentralized, serverless future, we have to talk about the trauma they inflicted on a generation of Solidity developers.&lt;/p&gt;

&lt;h3&gt;
  
  
  1. The Original Sin: USDT is not actually an ERC-20
&lt;/h3&gt;

&lt;p&gt;When you are deep in protocol-level engineering, you rely on standards. EIP-20 explicitly states that a token's &lt;code&gt;transfer&lt;/code&gt; and &lt;code&gt;transferFrom&lt;/code&gt; functions &lt;em&gt;must&lt;/em&gt; return a boolean value to indicate success or failure.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// The standard EIP-20 Interface
interface IERC20 {
    function transfer(address to, uint256 amount) external returns (bool);
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Tether completely ignored this. When they deployed the USDT contract, they omitted the return value entirely. Their functions return void.&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;// The actual USDT Mainnet Implementation (simplified)&lt;/span&gt;
&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;transfer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;address&lt;/span&gt; &lt;span class="nx"&gt;to&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;uint&lt;/span&gt; &lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="kr"&gt;public&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// ... logic ...&lt;/span&gt;
    &lt;span class="c1"&gt;// Notice: No return statement.&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you blindly write a vault or a swap contract using the standard IERC20 interface to move USDT, your transaction will seamlessly execute the logic, move the funds, and then violently revert at the very last microsecond.&lt;/p&gt;

&lt;p&gt;Why? Because modern Solidity uses a strict ABI decoder. When your contract calls USDT.transfer(), the EVM executes a low-level CALL. When the call finishes, Solidity checks the RETURNDATASIZE. Since it expects a bool (32 bytes), but USDT returns absolutely nothing (0 bytes), the decoder panics and reverts the entire transaction.&lt;/p&gt;

&lt;p&gt;For years, the only way to build DeFi safely with USDT has been to wrap it in OpenZeppelin's SafeERC20 library, which uses low-level assembly to explicitly check the return data size and bypass the strict ABI decoding:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";

contract Vault {
    using SafeERC20 for IERC20;
    IERC20 public usdt;

    function deposit(uint256 amount) external {
        // We have to use safeTransferFrom because USDT is non-compliant
        usdt.safeTransferFrom(msg.sender, address(this), amount);
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;So, imagine my skepticism. The company that deployed a non-compliant proxy contract that breaks standard EVM interfaces is now funding the most radical, bare-metal, peer-to-peer web infrastructure of the decade?&lt;/p&gt;

&lt;p&gt;It felt like a bad joke. Until I looked at the system architecture.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. The Geopolitics of Decentralized Routing
&lt;/h3&gt;

&lt;p&gt;Tether isn't funding Holepunch out of the goodness of their hearts. They are doing it out of existential necessity.&lt;/p&gt;

&lt;p&gt;Look at the architectural dependency graph of the modern financial system. Tether has achieved incredible product-market fit; USDT is the shadow dollar of the global south. But no matter how secure the Ethereum, Tron, or Solana blockchains are, the access layer to those blockchains is controlled by a tiny cartel of Web2 tech monopolies.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[ Traditional Web3 Access Flow ]

User Wallet (Browser) 
      │
      ▼
Cloud-Hosted React Frontend (AWS / Vercel) ──► DNS Providers (Cloudflare)
      │
      ▼
Centralized RPC Node (Infura / Alchemy)
      │
      ▼
The Blockchain (Decentralized)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If a sovereign state decides to sanction Tether, they don't have to attack the blockchain. They just force Amazon Web Services to drop the frontend hosting, force Cloudflare to revoke the DNS, and force Infura to block the RPC requests. The blockchain keeps ticking, but the users go dark.&lt;/p&gt;

&lt;p&gt;This is the exact vulnerability Tether is actively engineering out of existence.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Holepunch: Bypassing the Cloud
&lt;/h3&gt;

&lt;p&gt;By funding the Bare runtime and the Holepunch protocol, Tether is building an application delivery layer that completely bypasses centralized cloud infrastructure.&lt;br&gt;&lt;br&gt;
The Bitfinex Blog&lt;/p&gt;

&lt;p&gt;Instead of hosting a trading terminal on AWS, Tether can build a financial application where the binary, the UI, and the data are seeded via Hyperdrive (a BitTorrent-like distributed file system).&lt;/p&gt;

&lt;p&gt;When a user opens the application, they connect directly to other users via a Kademlia Distributed Hash Table (DHT). There is no DNS. There is no cloud server.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[ Holepunch P2P Access Flow ]

Peer A (User) ◄──────── (Noise IK Handshake via UDP) ────────► Peer B (User)
      │                                                           │
      └──► Local Application Logic &amp;amp; State (Seeded via DHT) ◄─────┘
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This isn't a blockchain. There is no global consensus, no blocks, and no gas fees. It is simply raw, encrypted, peer-to-peer data replication. Tether is building this to ensure that even if every cloud provider on earth blacklists them, people can still download, run, and communicate through their financial terminals.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Architect's Realization
&lt;/h3&gt;

&lt;p&gt;I spent hours frustrated by Tether's sloppy smart contract engineering. But looking at their macro-architecture, I have to respect the pivot.&lt;/p&gt;

&lt;p&gt;They realized that putting a stablecoin on a decentralized ledger is completely useless if the physical wires connecting the users are owned by three centralized corporations. They are funding a non-blockchain JavaScript runtime because they understand that true decentralization requires severing the dependency on the server entirely.&lt;/p&gt;

&lt;p&gt;We spend our time optimizing Solidity gas down to the byte and debating EVM storage slots. But if we don't start thinking about how our applications are actually distributed, we are just building decentralized sandcastles inside a centralized walled garden.&lt;/p&gt;

</description>
      <category>web3</category>
      <category>solidity</category>
      <category>architecture</category>
      <category>tether</category>
    </item>
    <item>
      <title>The Great Web3 Lie: AWS, Infura, and the Return of True Peer-to-Peer</title>
      <dc:creator>Aniket Misra</dc:creator>
      <pubDate>Sat, 04 Jul 2026 18:26:20 +0000</pubDate>
      <link>https://dev.to/aniket_misra_e47d1564ab7b/the-great-web3-lie-aws-infura-and-the-return-of-true-peer-to-peer-3d8f</link>
      <guid>https://dev.to/aniket_misra_e47d1564ab7b/the-great-web3-lie-aws-infura-and-the-return-of-true-peer-to-peer-3d8f</guid>
      <description>&lt;p&gt;There is a glaring, uncomfortable hypocrisy at the heart of modern Web3 engineering, and we all collectively agree to ignore it. &lt;/p&gt;

&lt;p&gt;We preach the gospel of the "unstoppable web." We write endless threads about censorship resistance, decentralized consensus, and sovereign infrastructure. We build brilliant, mathematically flawless zero-knowledge circuits and deploy them to immutable ledgers. &lt;/p&gt;

&lt;p&gt;And then, to actually let users interact with our cryptographic masterpieces, we wrap them in a React frontend, deploy it to Vercel, and route the transactions through an Infura RPC endpoint running on Amazon Web Services. &lt;/p&gt;

&lt;p&gt;If a centralized cloud provider decides to pull the plug on a data center in us-east-1, half of the "unstoppable" decentralized web goes completely dark. We haven't actually decentralized the internet; we have just decentralized the backend database while leaving the entire application delivery mechanism firmly in the hands of three massive tech monopolies. &lt;/p&gt;

&lt;p&gt;This architectural dissonance has been bothering me for a while. It is what happens when a financial movement (crypto) hijacks an architectural movement (distributed systems). But while digging through alternative runtimes outside of the EVM and Solana ecosystems, I stumbled onto something profoundly disruptive. It isn't a blockchain. It has no token. But it solves the exact infrastructural vulnerability that Web3 ignores. &lt;/p&gt;

&lt;p&gt;It is a stack built by Holepunch—specifically, the &lt;strong&gt;Pear Runtime&lt;/strong&gt; and its underlying engine, &lt;strong&gt;Bare&lt;/strong&gt;. &lt;/p&gt;

&lt;p&gt;When you strip away the marketing, Pear is essentially a modern, hyper-optimized resurrection of the 1990s BitTorrent ethos, applied directly to application development. It forces us to ask a terrifying question: what if true decentralization doesn't require global consensus at all?&lt;/p&gt;

&lt;p&gt;To understand why this is so subversive, you have to look at the traditional deployment model. When you build a modern application, you assume the existence of a server. Even Node.js and Deno fundamentally assume they are running on a machine that will sit in a data center, listen on a port, and serve state to thin clients over HTTP. &lt;/p&gt;

&lt;p&gt;The Holepunch architecture violently rejects this premise. &lt;/p&gt;

&lt;p&gt;When you build an app on Pear, there is no web server. There is no cloud hosting. The application’s source code, assets, and state are distributed via &lt;code&gt;Hyperdrive&lt;/code&gt;, a secure, real-time distributed peer-to-peer file system. When a user "downloads" a Pear application, they aren't fetching it from AWS; they are fetching the encrypted pieces from other users who are currently running the app. &lt;/p&gt;

&lt;p&gt;The moment you open the application, you become a seeder. The deployment infrastructure scales infinitely, automatically, and at zero cost, entirely powered by the aggregate compute of the users themselves. It is serverless, not in the sanitized AWS Lambda sense of the word, but in the literal, anarchic Napster sense. &lt;/p&gt;

&lt;p&gt;Under the hood, this requires a complete teardown of standard networking. You cannot rely on DNS to find a server that doesn't exist. Instead, Holepunch relies on &lt;code&gt;Hyperswarm&lt;/code&gt; and a Kademlia-based Distributed Hash Table (DHT). In this architecture, cryptography isn't used to reach a global financial consensus; it is used purely for routing. Your public cryptographic key becomes your global, static IP address. Devices perform a Noise IK handshake across the DHT, punch through their local NAT firewalls via UDP, and establish a direct, end-to-end encrypted tunnel.&lt;/p&gt;

&lt;p&gt;To make this viable, they had to ditch Node.js. Node is too bloated, carrying decades of legacy APIs designed for centralized web servers. Instead, they built &lt;strong&gt;Bare&lt;/strong&gt;—a stripped-down, modular C-based JavaScript runtime. Bare throws away the HTTP server assumptions. It keeps the V8 engine and the asynchronous event loop, but optimizes entirely for low-level, peer-to-peer data streams across desktop and mobile. &lt;/p&gt;

&lt;p&gt;This architecture fundamentally alters the threat model of the web. You cannot DDoS an application that has no central server. A government cannot compel a cloud provider to take down a user interface if that interface is being seeded dynamically by thousands of autonomous laptops across the globe. &lt;/p&gt;

&lt;p&gt;Web3 promised us an apocalypse-proof internet, but handed us a decentralized ledger heavily tethered to Silicon Valley cloud infrastructure. Seeing a stack like Pear proves that the actual missing layer of the "unstoppable web" was never about consensus mechanisms or tokenomics. It was about raw data availability. &lt;/p&gt;

&lt;p&gt;It turns out, if you want to build truly sovereign software, you have to stop trying to put the server on the blockchain, and simply kill the server altogether. &lt;/p&gt;

&lt;p&gt;Next time, I am going to dive deeper into why the company behind the $100 billion stablecoin USDT (Tether) is the one secretly bankrolling this entire non-blockchain JavaScript ecosystem, because the geopolitical implications of that are wild.&lt;/p&gt;

</description>
      <category>web3</category>
      <category>p2p</category>
      <category>architecture</category>
      <category>systems</category>
    </item>
    <item>
      <title>The Architecture Spiral: RPC, SQL, and the Myth of Linear Evolution</title>
      <dc:creator>Aniket Misra</dc:creator>
      <pubDate>Wed, 01 Jul 2026 12:42:20 +0000</pubDate>
      <link>https://dev.to/aniket_misra_e47d1564ab7b/the-architecture-spiral-rpc-sql-and-the-myth-of-linear-evolution-3dp7</link>
      <guid>https://dev.to/aniket_misra_e47d1564ab7b/the-architecture-spiral-rpc-sql-and-the-myth-of-linear-evolution-3dp7</guid>
      <description>&lt;p&gt;If you sit in on enough system design meetings, you inevitably witness the exact same debate play out on a repeating loop. It usually starts when a team is breaking down a monolithic backend and trying to figure out how the new microservices should talk to each other. &lt;/p&gt;

&lt;p&gt;Someone suggests standard REST. It’s stateless, ubiquitous, and deeply understood. &lt;br&gt;
Then, a more performance-minded engineer interjects: &lt;em&gt;"JSON over HTTP/1.1 is too heavy for internal service-to-service chatter. We need strict contracts and lower latency. Let's use gRPC."&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;It feels like a hyper-modern debate—the battle-tested standard of the 2010s versus the cutting-edge, high-performance tooling of the 2020s. &lt;/p&gt;

&lt;p&gt;But if you zoom out, the illusion of modern innovation shatters. Remote Procedure Call (RPC) isn't new. It was conceptualized in the 1970s and standardized in the 1980s. We aren't inventing a new way for computers to communicate; we are just resurrecting a 50-year-old paradigm, dressing it in Protobufs, and multiplexing it over HTTP/2.&lt;/p&gt;

&lt;p&gt;This is the quiet truth of software engineering: &lt;strong&gt;Technological progress is not a straight line. It is a spiral.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;We rarely invent entirely new architectures. Instead, we revisit the exact same fundamental concepts, just one layer higher on the Z-axis of abstraction. &lt;/p&gt;




&lt;h2&gt;
  
  
  1. The REST vs. RPC Pendulum
&lt;/h2&gt;

&lt;p&gt;To understand the spiral, look at how we got to REST in the first place. &lt;/p&gt;

&lt;p&gt;In the late 90s and early 2000s, RPC implementations (like CORBA, DCOM, and SOAP) were miserable. They were tightly coupled, brittle, and notoriously difficult to debug across different languages. If a developer updated a method signature on a server, clients across the network would immediately fracture.&lt;/p&gt;

&lt;p&gt;Roy Fielding’s REST (Representational State Transfer) won the web because it provided the ultimate decoupled escape hatch. Instead of executing remote &lt;em&gt;actions&lt;/em&gt;, clients interacted with remote &lt;em&gt;resources&lt;/em&gt; using standardized, predictable HTTP verbs. It was beautiful, cacheable, and heavily adopted.&lt;/p&gt;

&lt;p&gt;But as we transitioned into the era of distributed microservices, REST hit a wall. When you have 40 internal services pinging each other to fulfill a single user request, the overhead of parsing massive JSON payloads and managing stateless HTTP connections becomes a devastating bottleneck. &lt;/p&gt;

&lt;p&gt;So, what did we do? We went right back to RPC. &lt;/p&gt;

&lt;p&gt;We realized that for internal, tightly-bound systems, we actually &lt;em&gt;wanted&lt;/em&gt; strict coupling. We wanted type safety. We wanted binary serialization. Tools like gRPC and tRPC dominate modern backend discussions not because they are conceptually novel, but because they are the 1980s RPC architecture built with 2020s infrastructure.&lt;/p&gt;




&lt;h2&gt;
  
  
  2. The Return of the Relational Database
&lt;/h2&gt;

&lt;p&gt;You can see this same spiral evolution in data storage. &lt;/p&gt;

&lt;p&gt;If you were building a startup around 2012, you were explicitly told that relational databases were legacy tech. "SQL is dead," the thought leaders said. "Schema-less NoSQL is web-scale." We poured billions of dollars into document stores like MongoDB and wide-column stores like Cassandra, convinced that abandoning the rigid constraints of tables and foreign keys was the only way to achieve horizontal scalability.&lt;/p&gt;

&lt;p&gt;Fast forward to today. What is the default, undisputed king of databases? &lt;strong&gt;PostgreSQL.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Not only has SQL made a dominant comeback, but the very NoSQL databases that tried to kill it have spent the last five years desperately bolting SQL-like query languages onto their engines. &lt;/p&gt;

&lt;p&gt;Why did this happen? Because Edgar F. Codd’s "Relational Model of Data," published in 1970, wasn't just a technological trend. It was based on fundamental relational algebra. The math was always correct. The only problem in the 2010s was that the underlying &lt;em&gt;storage engines&lt;/em&gt; struggled to distribute that math across multiple physical servers. &lt;/p&gt;

&lt;p&gt;Once engineers figured out how to build distributed, globally consistent relational engines (like Google Spanner or CockroachDB), the need for NoSQL evaporated for 95% of use cases. We went right back to SQL.&lt;/p&gt;




&lt;h2&gt;
  
  
  3. Mainframes to Edge: The Physics of Compute
&lt;/h2&gt;

&lt;p&gt;Perhaps the most massive spiral is where compute actually happens. &lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;The 1970s (Centralized):&lt;/strong&gt; The era of the Mainframe. Massive central computers handled all the logic. Users interacted via "dumb terminals" on their desks that did nothing but render the output. &lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The 1990s (Decentralized):&lt;/strong&gt; The era of the Personal Computer. Moore’s Law made chips cheap. We moved compute away from the center and put it directly on the user's desk. &lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The 2010s (Centralized):&lt;/strong&gt; The era of the Cloud. We realized managing thousands of local machines was a nightmare. So, we moved the compute back to massive centralized data centers (AWS, GCP). Our high-powered laptops essentially became very expensive, glowing dumb terminals for web browsers.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The 2020s (Decentralized):&lt;/strong&gt; The era of the Edge. The cloud is now too slow for AI inference and high-performance UX. So, via WebAssembly (Wasm), local-first databases (SQLite in the browser), and edge networking, we are pushing the compute right back down to the user's local machine.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Mainframe to PC. Cloud to Edge. It is the exact same architectural breath, inhaling and exhaling across decades.&lt;/p&gt;




&lt;h2&gt;
  
  
  Why the Spiral?
&lt;/h2&gt;

&lt;p&gt;Why do we constantly go backwards to move forwards? Is it just a lack of imagination? Are we victims of sunk cost, clinging to the paradigms we learned in university?&lt;/p&gt;

&lt;p&gt;No. The spiral exists because software architecture is ultimately bound by physical reality. &lt;/p&gt;

&lt;p&gt;We are constantly negotiating between conflicting, immutable constraints: the speed of light (network latency), the cost of silicon (compute power), and the CAP theorem (consistency vs. availability). &lt;/p&gt;

&lt;p&gt;When we invent a "new" paradigm, we are usually just optimizing for one of these constraints by willingly sacrificing another. When we moved to NoSQL, we sacrificed consistency for availability. When we moved to the Cloud, we sacrificed latency for centralized management. &lt;/p&gt;

&lt;p&gt;Eventually, we push a paradigm to its absolute breaking point. We hit the physical limit of what it can do. And the only way out is to flip the trade-off, looking back into the past for the architecture that optimized for the exact thing we are now starving for.&lt;/p&gt;

&lt;p&gt;We aren't failing to innovate. We are just maturing. We are slowly realizing that the engineers of the 1970s weren't primitive; they were dealing with the exact same fundamental laws of computer science that we are. We just happen to have faster Wi-Fi.&lt;/p&gt;

</description>
      <category>architecture</category>
      <category>backend</category>
      <category>systems</category>
      <category>web3</category>
    </item>
    <item>
      <title>The Rhythm of the Primitives: Cryptography, Poisson, and the False Memory of the 90s</title>
      <dc:creator>Aniket Misra</dc:creator>
      <pubDate>Tue, 30 Jun 2026 18:28:59 +0000</pubDate>
      <link>https://dev.to/aniket_misra_e47d1564ab7b/the-rhythm-of-the-primitives-cryptography-poisson-and-the-false-memory-of-the-90s-1h1c</link>
      <guid>https://dev.to/aniket_misra_e47d1564ab7b/the-rhythm-of-the-primitives-cryptography-poisson-and-the-false-memory-of-the-90s-1h1c</guid>
      <description>&lt;p&gt;When we look back at the 1990s, our collective cultural memory betrays us. We retroactively paint the decade as an era of primitive digital toys—a neon-tinted landscape of screeching dial-up modems, bulky pagers, and kids feeding pixelated Tamagotchis. We treat it like the infancy of the digital age, a time before real engineering took hold.&lt;/p&gt;

&lt;p&gt;But a funny thing happens when you step away from modern abstractions, sit down with a Rust compiler, and read Satoshi Nakamoto’s 2008 whitepaper in its original context. The illusion shatters. You realize that the foundational architecture of decentralized consensus wasn't invented in the wake of the 2008 financial crisis. Every single piece of the cryptographic puzzle was already breathing, compiling, and thriving in that exact "primitive" decade. &lt;/p&gt;

&lt;p&gt;Satoshi didn't invent Web3. He was just the ultimate systems integrator. &lt;/p&gt;

&lt;p&gt;Digging into the cypherpunk archives of early Usenet groups is like walking into an ancient library and finding the blueprints for a spaceship. The intellectual breeding ground for decentralized technology was fully formed while the rest of the world was struggling to load JPEGs. The concept of sovereign-less "electronic money" was relentlessly debated. Wei Dai’s B-money and Nick Szabo’s Bit Gold laid the philosophical groundwork. The data structures required to keep a ledger lightweight—Merkle Trees—had already been patented by Ralph Merkle back in 1979. &lt;/p&gt;

&lt;p&gt;The missing link was always sybil resistance. How do you stop a malicious actor from spinning up a million fake identities to rewrite the ledger? The answer was sitting in 1997 with Adam Back’s Hashcash. Hashcash wasn't designed for global finance; it was a clever, brute-force hack to make email spam economically unviable by forcing a computer to expend CPU cycles to calculate a cryptographic hash. &lt;/p&gt;

&lt;p&gt;Satoshi took this anti-spam mechanism, lifted it from the forgotten corners of the 90s internet, and weaponized it into the heartbeat of global consensus. &lt;/p&gt;

&lt;p&gt;But where the whitepaper transitions from a clever engineering integration into an absolute masterpiece is in its mathematical rigor. Satoshi didn't just theorize that a decentralized network was secure; he proved it statistically. In the quietest, most devastatingly elegant section of the paper, he addresses the system's core vulnerability—a 51% attack—by framing it as a Binomial Random Walk. &lt;/p&gt;

&lt;p&gt;It is the classic Gambler’s Ruin problem applied to global finance. If an honest node has a probability (p) of finding the next block, and a malicious attacker has a probability (q, which is 1-p, that is, unless we are in a universe with probabilities&amp;gt;100%), the math becomes a beautiful, brutal reality. Because block discovery is probabilistic, Satoshi maps the attacker's potential progress to a Poisson distribution. &lt;/p&gt;

&lt;p&gt;He proves, with cold mathematical certainty, that as long as honest nodes control more CPU power (p &amp;gt; q), the probability of an attacker successfully rewriting history drops exponentially with every passing block. It is a masterpiece of statistical poetry. He built a trustless system by mathematically proving that betrayal is too expensive.&lt;/p&gt;

&lt;p&gt;Uncovering these anachronisms in technology—realizing that the heavy cryptographic lifting was happening parallel to the Tamagotchi—triggered a weird cognitive dissonance. It made me question what else I was misremembering about that era. Being a musician, I naturally turned to the rhythm of the decade.&lt;/p&gt;

&lt;p&gt;For my entire life, I have retrospectively framed the 90s as the decade of relentless, underground Eurotechno. In my head, the soundtrack of that era was an endless loop of Haddaway’s "What is Love" thumping out of a dark, synthesized European club basement. I equated the 90s with the four-on-the-floor kick drum of early electronic dance music.&lt;/p&gt;

&lt;p&gt;I was completely wrong. Look at the actual cultural footprint of the decade. It wasn't defined by cold European synthesizers; it was a massively hispanophile era. The &lt;em&gt;Macarena&lt;/em&gt; didn't just exist; it conquered the globe. Latin pop exploded into the global mainstream. The rhythm of the decade was fundamentally organic, percussive, and intensely Latin. The aesthetic I had projected onto the past was a complete fabrication.&lt;/p&gt;

&lt;p&gt;This historical unearthing has bled into my own physical reality. I’ve realized that my own rhythms need a structural shift. The tabla is a beautiful, complex instrument, and it will always be a part of my percussive foundation. But you cannot lug a heavy set of brass and wood up a mountain on a hike. It is geographically anchoring. &lt;/p&gt;

&lt;p&gt;So, I’m reviving my old school assembly chops. I am packing up the bongos. They fit in a backpack. They carry that organic, Afro-Cuban groove that actually defined the era I’ve been misremembering. And to make sure I’m not just an isolated rhythm section on the trail, I’ve picked up a harmonica to build out some melodic grit. &lt;/p&gt;

&lt;p&gt;Afro-Cuban percussion and delta Blues are officially on. It turns out, whether you are integrating 1990s cypherpunk primitives to build decentralized state machines, or blending bongos with a blues harp on a hiking trail, the magic is never in inventing something entirely new. The magic is in the assembly. &lt;/p&gt;

&lt;p&gt;Time to get back to the Rust compiler.&lt;/p&gt;

</description>
      <category>cryptography</category>
      <category>history</category>
      <category>music</category>
      <category>rust</category>
    </item>
    <item>
      <title>The Architecture of Trust: Reading Satoshi’s Whitepaper in an Era of Category Errors</title>
      <dc:creator>Aniket Misra</dc:creator>
      <pubDate>Tue, 23 Jun 2026 20:26:28 +0000</pubDate>
      <link>https://dev.to/aniket_misra_e47d1564ab7b/the-architecture-of-trust-reading-satoshis-whitepaper-in-an-era-of-category-errors-23a3</link>
      <guid>https://dev.to/aniket_misra_e47d1564ab7b/the-architecture-of-trust-reading-satoshis-whitepaper-in-an-era-of-category-errors-23a3</guid>
      <description>&lt;p&gt;Immediately after putting down my Rust compiler, I did something I should have done years ago: I sat down and read Satoshi Nakamoto’s original 2008 Bitcoin whitepaper from start to finish. &lt;/p&gt;

&lt;p&gt;If you spend any time in the modern Web3 ecosystem, opening that 11-page document is an absolute culture shock. &lt;/p&gt;

&lt;p&gt;There are no modern buzzwords. You won't find the terms "blockchain," "smart contracts," "layer-2s," "tokenomics," or "decentralized applications." Instead, you are met with a masterclass in pragmatic, systems-level engineering terminology. Nakamoto doesn't write like a venture capitalist or a hype-merchant; he writes like a practical systems architect solving a structural database flaw. &lt;/p&gt;




&lt;h2&gt;
  
  
  1. The Simplistic Language of a Systems Engineer
&lt;/h2&gt;

&lt;p&gt;The language of the whitepaper is strikingly plain, almost archaic by today’s standards. What we now call a blockchain, Satoshi simply calls a &lt;strong&gt;"peer-to-peer distributed timestamp server."&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[ Transactions ] ──► [ Hashed into a Block ] ──► [ Timestamped ] ──► [ Broadcast to Network ]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;&lt;br&gt;
plaintext&lt;/p&gt;

&lt;p&gt;He doesn’t rely on abstract philosophy to justify the system. He frames the entire invention around a single, concrete engineering problem: &lt;strong&gt;eliminating the double-spending problem without relying on a trusted third party.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The beauty of the whitepaper lies in how it constructs a massive trust network entirely out of simple, existing components:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;A chain of digital signatures&lt;/strong&gt; to track ownership vectors.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;A Proof-of-Work hash puzzle&lt;/strong&gt; (borrowed from Adam Back's Hashcash) to achieve distributed consensus.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;An incentive loop&lt;/strong&gt; (block rewards and transaction fees) to align the self-interest of independent hardware operators with the security of the network.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Satoshi’s genius wasn't inventing a single new cryptographic primitive; it was the brilliant coordination of existing primitives into an elegant, self-sustaining loop. It is a reminder that great architecture isn't about complexity—it’s about minimizing structural dependencies.&lt;/p&gt;


&lt;h2&gt;
  
  
  2. Has Modern Banking Fixed its 2008 Structural Flaws?
&lt;/h2&gt;

&lt;p&gt;Satoshi famously carved the message &lt;em&gt;"The Times 03/Jan/2009 Chancellor on brink of second bailout for banks"&lt;/em&gt; into Bitcoin's genesis block. It was a direct response to the systemic counterparty risk that triggered the 2008 financial crisis. &lt;/p&gt;

&lt;p&gt;Nearly two decades later, the question arises: has modern commercial banking actually solved the structural vulnerability that Bitcoin was built to bypass?&lt;/p&gt;

&lt;p&gt;From a technical and regulatory standpoint, the system has introduced massive patches:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Basel III &amp;amp; IV Compliance:&lt;/strong&gt; Imposing significantly higher capital reserve requirements, stricter liquidity ratios, and rigorous stress-testing on global systemically important banks (G-SIBs).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Real-Time Gross Settlement (RTGS):&lt;/strong&gt; Systems like FedNow or instant-payment rails have optimized transaction speed, reducing the clearing windows where systemic settlement risk can accumulate.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;But beneath these operational optimizations, &lt;strong&gt;the fundamental architecture remains unchanged.&lt;/strong&gt; The modern banking system still runs on fractional reserves, ledger opacity, and centralized, institutional trust layers. As we saw during the banking failures of early 2023 (Silicon Valley Bank, Signature Bank, Credit Suisse), risk hasn't been engineered out of the system; it has simply been heavily managed, subsidized, and backstopped by central bank liquidity. When confidence drops, the centralized ledger remains vulnerable to old-school bank runs, accelerated by modern digital speeds.&lt;/p&gt;


&lt;h2&gt;
  
  
  3. The Category Error: Demanding Trustlessness from Commercial Systems
&lt;/h2&gt;

&lt;p&gt;This brings us to a fundamental architectural misunderstanding often made when comparing traditional finance (TradFi) to decentralized protocols: &lt;strong&gt;looking for "trustlessness" in a non-blockchain commercial banking system is a complete category error.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Commercial banking and public blockchains are built on entirely distinct, non-overlapping design philosophies.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;┌─────────────────────────────────┐       ┌─────────────────────────────────┐
│     COMMERCIAL BANKING L3       │       │       BLOCKCHAIN PROTOCOLS      │
├─────────────────────────────────┤       ├─────────────────────────────────┤
│ • Optimization: Speed &amp;amp; Credit  │       │ • Optimization: Fault Tolerance │
│ • Core Mechanism: Legal Trust   │       │ • Core Mechanism: Computation   │
│ • State: Subjective / Reversible│       │ • State: Objective / Immutable  │
└─────────────────────────────────┘       └─────────────────────────────────┘
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Legal Trust vs. Computational Verification
&lt;/h3&gt;

&lt;p&gt;Commercial banking is explicitly engineered to maximize &lt;strong&gt;capital efficiency, credit expansion, and transaction throughput.&lt;/strong&gt; To achieve this, it relies on an architectural layer of &lt;em&gt;subjective trust&lt;/em&gt; backed by legal frameworks, identity verification, state enforcement, and human mediation. If a transaction is fraudulent, a centralized authority can manually reverse the state of the ledger. Reversibility requires trust.&lt;/p&gt;

&lt;p&gt;Bitcoin and decentralized protocols optimize for &lt;strong&gt;fault tolerance, censorship resistance, and absolute settlement finality.&lt;/strong&gt; To achieve this, they purposefully sacrifice raw speed and capital flexibility. The state transitions are &lt;em&gt;objective&lt;/em&gt;—enforced strictly by mathematics and distributed physical computation.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Conclusion
&lt;/h3&gt;

&lt;p&gt;You cannot build a trustless commercial bank because the moment you introduce credit issuance, debt underwriting, and subjective dispute resolution, you require a centralized trusted human arbiter. &lt;/p&gt;

&lt;p&gt;Conversely, the moment you introduce a trusted human arbiter to a blockchain protocol, you break its entire security model.&lt;/p&gt;

&lt;p&gt;Reading Satoshi’s whitepaper highlights that Web3 shouldn't try to replicate the subjective, credit-driven architecture of modern commercial systems. Our objective as protocol engineers is to build clean, immutable, deterministic execution environments where trust is completely offloaded to math and code. &lt;/p&gt;




&lt;p&gt;&lt;em&gt;This concludes my two-part reflection on systems thinking—from the raw event-driven instincts of a child hacking Lua in a sandbox, to the elegant, buzzword-free architecture laid down by Satoshi in 2008. Time to get back to writing Rust. I'm targeting writing a reverse proxy in rust to get the feel of it, maybe compare it to a similar construct in typescript, and finally clarify my knowledge on reverse proxy vs api gateway vs load balancer by writing them.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>bitcoin</category>
      <category>blockchain</category>
      <category>web3</category>
      <category>systems</category>
    </item>
    <item>
      <title>The Sandbox Prodigies: Roblox, Event-Driven Logic, and the Future of Engineering</title>
      <dc:creator>Aniket Misra</dc:creator>
      <pubDate>Tue, 23 Jun 2026 20:18:17 +0000</pubDate>
      <link>https://dev.to/aniket_misra_e47d1564ab7b/the-sandbox-prodigies-roblox-event-driven-logic-and-the-future-of-engineering-4cmd</link>
      <guid>https://dev.to/aniket_misra_e47d1564ab7b/the-sandbox-prodigies-roblox-event-driven-logic-and-the-future-of-engineering-4cmd</guid>
      <description>&lt;p&gt;A few days ago, my 11-year-old relative showed me a snippet of code he was hacking together for a custom game in Roblox. It wasn't clean, syntactically valid Lua—it was a chaotic, stream-of-consciousness pseudo-script mashed into his editor. &lt;/p&gt;

&lt;p&gt;It looked exactly like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight lua"&gt;&lt;code&gt;&lt;span class="n"&gt;setmetatable&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;random&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;match&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;rawequal&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;config&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;real&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;parent&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;checkpoint&lt;/span&gt;
&lt;span class="n"&gt;can&lt;/span&gt; &lt;span class="n"&gt;collide&lt;/span&gt;&lt;span class="p"&gt;.(&lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;anchored&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="ow"&gt;and&lt;/span&gt; &lt;span class="k"&gt;then&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;cooldown&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;concat&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="ow"&gt;and&lt;/span&gt; &lt;span class="k"&gt;then&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;can&lt;/span&gt; &lt;span class="n"&gt;run&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="n"&gt;loop&lt;/span&gt;
&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;parent&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;control&lt;/span&gt; &lt;span class="n"&gt;player&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you feed this into a compiler, it throws a syntax error on line one. But if you look past the malformed syntax and analyze the structural intent, it is absolutely fascinating. &lt;/p&gt;

&lt;p&gt;An 11-year-old kid is organically reasoning about complex computer science paradigms that university students struggle with in sophomore year systems classes. &lt;/p&gt;




&lt;h2&gt;
  
  
  Deconstructing the 11-Year-Old's System Design
&lt;/h2&gt;

&lt;p&gt;Look at what is actually happening in that broken snippet:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Metatables and OOP Overrides:&lt;/strong&gt; He kicks off with &lt;code&gt;setmetatable&lt;/code&gt; and &lt;code&gt;rawequal&lt;/code&gt;. In Lua, metatables are the underlying mechanism used to implement Object-Oriented Programming, operator overloading, and prototype inheritance. He doesn't know the academic definition of a prototype pattern, but he intuitively understands that he needs to override default behaviors to match specific data conditions.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;State Management and Properties:&lt;/strong&gt; &lt;code&gt;can collide.(false)&lt;/code&gt; and &lt;code&gt;anchored(true)&lt;/code&gt;. He is explicitly manipulating the physics engine properties of a 3D environment—turning off collision matrices and locking spatial vectors in world space.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Asynchronous Flow and Loop Logic:&lt;/strong&gt; &lt;code&gt;and then.cooldown=(3)&lt;/code&gt; followed by &lt;code&gt;concat=and then.can run in loop&lt;/code&gt;. This is the most striking part. He is conceptualizing a state machine that handles debouncing (cooldowns), asynchronous continuation (&lt;code&gt;and then&lt;/code&gt; resembles a JavaScript Promise abstraction), and recursive execution loops.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Conditional Execution Hooks:&lt;/strong&gt; &lt;code&gt;if parent.control player&lt;/code&gt;. He is defining a conditional interceptor based on an object's hierarchical structural tree to determine identity and execution control.&lt;/li&gt;
&lt;/ol&gt;




&lt;h2&gt;
  
  
  The Power of the Enshrined Event-Driven Sandbox
&lt;/h2&gt;

&lt;p&gt;What enables a child to reason like this before they even understand basic algebraic geometry? &lt;strong&gt;The sandbox environment.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Platforms like Roblox and Minecraft have done something incredible: they have wrapped high-performance, event-driven game engines in low-friction, highly interactive playgrounds. Kids aren't learning programming by printing "Hello World" to a static terminal. They are learning programming by modifying live, reactive systems.&lt;/p&gt;

&lt;p&gt;They learn through a pure &lt;strong&gt;event-driven feedback loop&lt;/strong&gt;. They change a property, an object falls through the floor, and they immediately understand the physical consequence of their logic. The event loop is no longer an abstract thread management concept discussed in systems architecture books; it is the concrete reality of their game world.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Structural Implications on a Future Career
&lt;/h2&gt;

&lt;p&gt;When a kid starts thinking in terms of state manipulation, loops, overrides, and inheritance models at age 11, it completely rewires their cognitive approach to engineering. &lt;/p&gt;

&lt;p&gt;By the time this kid sits down in a university or corporate setting, the hard part of software engineering—&lt;strong&gt;structural systems thinking&lt;/strong&gt;—will be second nature. He won't see code as a sequence of text strings; he will see it as a reactive architecture of interlocking components.&lt;/p&gt;

&lt;p&gt;Whether he ends up writing low-level protocol engines, designing high-throughput distributed systems, or building smart contracts, or ends up a neovim larper like this guy &lt;a href="https://www.youtube.com/c/theprimeagen" rel="noopener noreferrer"&gt;ThePrimeAgen&lt;/a&gt; the foundation is the same. He is already building the mental scaffolding required to manage complex state transitions in public sandboxes.&lt;/p&gt;

&lt;p&gt;The tools change, the syntax hardens, but the core engineering instinct remains identical. The sandbox prodigies aren't just playing games—they are subtly training to become the systems architects of tomorrow.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;This is Part 1 of a loose series of reflections on how we learn, read, and build systems. Part 2 will dive into a completely different kind of foundational architecture: my recent breakdown of Satoshi Nakamoto's original Bitcoin whitepaper and its surprisingly archaic systems language.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>programming</category>
      <category>roblox</category>
      <category>lua</category>
      <category>buildinginpublic</category>
    </item>
  </channel>
</rss>
