<?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: Aditya Srivastava</title>
    <description>The latest articles on DEV Community by Aditya Srivastava (@vastavadi).</description>
    <link>https://dev.to/vastavadi</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3949452%2F4823cb54-3303-4787-ba6c-00de3fcc534f.jpeg</url>
      <title>DEV Community: Aditya Srivastava</title>
      <link>https://dev.to/vastavadi</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/vastavadi"/>
    <language>en</language>
    <item>
      <title>Node.js vs Bun vs Go - A Multi-Layer HTTP Benchmark</title>
      <dc:creator>Aditya Srivastava</dc:creator>
      <pubDate>Sun, 24 May 2026 19:22:29 +0000</pubDate>
      <link>https://dev.to/vastavadi/nodejs-vs-bun-vs-go-30a1</link>
      <guid>https://dev.to/vastavadi/nodejs-vs-bun-vs-go-30a1</guid>
      <description>&lt;h1&gt;
  
  
  🚀 Node.js vs Bun vs Go: A Multi-Layer HTTP Benchmark
&lt;/h1&gt;

&lt;h2&gt;
  
  
  🎯 Premise
&lt;/h2&gt;

&lt;p&gt;I came across a video discussing Bun's new native image support claiming "blazing fast" performance. As a software developer with 4+ years building Node services, I wanted to quantify Bun's actual performance characteristics compared to Node.js in realistic scenarios.&lt;/p&gt;

&lt;p&gt;I included Go as a baseline representing compiled, systems-level performance to contextualize the JavaScript runtime results.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;⚡ What this benchmark tests:&lt;/strong&gt; Raw HTTP throughput serving static JSON responses&lt;br&gt;&lt;br&gt;
&lt;strong&gt;❌ What this benchmark does NOT test:&lt;/strong&gt; Database I/O, JSON parsing, real application logic, memory pressure, error handling, or long-tail latency under sustained load&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  🔬 Methodology: From Localhost to Cloud
&lt;/h2&gt;

&lt;p&gt;Localhost benchmarks often produce misleading results because they test memory bus speeds rather than real-world network and system constraints. To uncover performance across different bottleneck layers, I tested three phases:&lt;/p&gt;

&lt;h3&gt;
  
  
  📊 Test Phases
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Phase&lt;/th&gt;
&lt;th&gt;Environment&lt;/th&gt;
&lt;th&gt;What It Reveals&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;1️⃣ Localhost&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Loopback interface&lt;/td&gt;
&lt;td&gt;Pure event loop overhead&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;2️⃣ LAN over Tailscale&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;WiFi network&lt;/td&gt;
&lt;td&gt;Network I/O constraints&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;3️⃣ Cloud Datacenter&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;DigitalOcean droplets&lt;/td&gt;
&lt;td&gt;Removes local hardware limits&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h3&gt;
  
  
  ⚙️ Test Configuration
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Workload:&lt;/strong&gt; &lt;code&gt;GET /json&lt;/code&gt; → &lt;code&gt;{"message": "Hello from [runtime]"}&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Hardware:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;💻 &lt;strong&gt;Local:&lt;/strong&gt; Windows dev machine, Tenda U10 USB WiFi adapter (WiFi 3)&lt;/li&gt;
&lt;li&gt;☁️ &lt;strong&gt;Cloud:&lt;/strong&gt; DigitalOcean shared droplets (burstable vCPUs), 10 Gbps datacenter network&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Load generator:&lt;/strong&gt; &lt;code&gt;wrk -t2 -c200 -d30s&lt;/code&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;⚠️ &lt;strong&gt;Important:&lt;/strong&gt; Each test was run once. For production decisions, you'd want 5+ runs with statistical analysis (median, stddev, confidence intervals).&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  🏁 Phase 1: Localhost Baseline
&lt;/h2&gt;

&lt;p&gt;Testing over the loopback interface to measure pure event loop and syscall overhead without network constraints.&lt;/p&gt;

&lt;h3&gt;
  
  
  📈 Results: Local Memory Performance
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Configuration&lt;/th&gt;
&lt;th&gt;Node.js&lt;/th&gt;
&lt;th&gt;Bun&lt;/th&gt;
&lt;th&gt;Go&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;1 CPU Core&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;~14,000 RPS&lt;/td&gt;
&lt;td&gt;~28,000 RPS&lt;/td&gt;
&lt;td&gt;~29,000 RPS&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;4 CPU Cores (Single Process)&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;~16,000 RPS&lt;/td&gt;
&lt;td&gt;~30,000 RPS&lt;/td&gt;
&lt;td&gt;
&lt;strong&gt;~115,000 RPS&lt;/strong&gt; 🚀&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;4 CPU Cores (Multi-Process)&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;~110,000 RPS&lt;/td&gt;
&lt;td&gt;
&lt;strong&gt;~170,000 RPS&lt;/strong&gt; 🏆&lt;/td&gt;
&lt;td&gt;&lt;em&gt;N/A&lt;/em&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h3&gt;
  
  
  💡 Analysis
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;🧵 Single-threaded bottleneck:&lt;/strong&gt; Node and Bun's JavaScript execution is single-threaded. Without process clustering, they max out one CPU core even with &lt;code&gt;--cpus="4"&lt;/code&gt;, leaving 3 cores idle. Go's M:N scheduler automatically utilizes all available cores in a single process.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;📊 Multi-process scaling:&lt;/strong&gt; Once clustered (Node's &lt;code&gt;cluster&lt;/code&gt; module, Bun with &lt;code&gt;reusePort: true&lt;/code&gt; spawned 4 times), both JavaScript runtimes showed strong scaling. Bun's lighter-weight Zig event loop showed &lt;strong&gt;~55% higher throughput&lt;/strong&gt; than Node's V8-based implementation.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;✅ What this tells us:&lt;/strong&gt; For CPU-bound workloads on the loopback interface, Bun's event loop has measurably lower per-request overhead than Node. Go's native multi-core scheduling eliminates the need for manual clustering.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  🌐 Phase 2: Network-Constrained Reality (Tailscale over WiFi)
&lt;/h2&gt;

&lt;p&gt;Requests now traverse a physical network: MacBook → USB WiFi adapter → Tailscale WireGuard VPN → Windows dev machine.&lt;/p&gt;

&lt;h3&gt;
  
  
  📊 Results: Network-Bound I/O (4 Cores, Clustered)
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Metric&lt;/th&gt;
&lt;th&gt;Node.js&lt;/th&gt;
&lt;th&gt;Bun&lt;/th&gt;
&lt;th&gt;Go&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Throughput&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;7,954 RPS&lt;/td&gt;
&lt;td&gt;12,519 RPS&lt;/td&gt;
&lt;td&gt;
&lt;strong&gt;12,873 RPS&lt;/strong&gt; 🏆&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Avg Latency&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;26.79 ms&lt;/td&gt;
&lt;td&gt;16.49 ms&lt;/td&gt;
&lt;td&gt;
&lt;strong&gt;15.69 ms&lt;/strong&gt; ⚡&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Max Latency&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;864.53 ms ⚠️&lt;/td&gt;
&lt;td&gt;163.24 ms&lt;/td&gt;
&lt;td&gt;
&lt;strong&gt;152.21 ms&lt;/strong&gt; ✅&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Bandwidth&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;1.62 MB/s&lt;/td&gt;
&lt;td&gt;1.76 MB/s&lt;/td&gt;
&lt;td&gt;1.67 MB/s&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h3&gt;
  
  
  💡 Analysis
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;🔌 Network becomes the bottleneck:&lt;/strong&gt; All three runtimes collapsed from 30k-170k RPS to 8-13k RPS. The WiFi 3 USB adapter (theoretical max ~54 Mbps, real-world much lower) became the limiting factor.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;⚠️ Node's outlier spike:&lt;/strong&gt; The 864ms max latency suggests either:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Garbage collection pause under network pressure&lt;/li&gt;
&lt;li&gt;IPC coordination delays between cluster master/workers when packets arrive in bursts&lt;/li&gt;
&lt;li&gt;Should have been investigated with proper GC tuning flags and p99 analysis&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;📌 What this tells us:&lt;/strong&gt; This phase primarily measured my WiFi adapter's limitations, not runtime performance. However, it does show that once network I/O becomes the constraint, runtime choice matters less than network hardware quality.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  ☁️ Phase 3: Cloud Infrastructure (1 Core)
&lt;/h2&gt;

&lt;p&gt;Moved to DigitalOcean droplets to remove local hardware constraints. Target and load generator in same datacenter.&lt;/p&gt;

&lt;h3&gt;
  
  
  🐳 Docker Configuration
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker run &lt;span class="nt"&gt;--rm&lt;/span&gt; &lt;span class="nt"&gt;--cpus&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"1"&lt;/span&gt; &lt;span class="nt"&gt;-m&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"512m"&lt;/span&gt; &lt;span class="nt"&gt;-p&lt;/span&gt; 3000:3000 &lt;span class="o"&gt;[&lt;/span&gt;image]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;⚠️ &lt;strong&gt;Note:&lt;/strong&gt; &lt;code&gt;--cpus="1"&lt;/code&gt; uses CFS CPU quotas, not core pinning. The container can still migrate between physical cores, introducing cache invalidation. Should have used &lt;code&gt;--cpuset-cpus="0"&lt;/code&gt; for true single-core isolation.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  📊 Results: Cloud Single-Core
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Metric&lt;/th&gt;
&lt;th&gt;Node.js&lt;/th&gt;
&lt;th&gt;Go&lt;/th&gt;
&lt;th&gt;Bun&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Throughput&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;11,705 RPS&lt;/td&gt;
&lt;td&gt;13,935 RPS&lt;/td&gt;
&lt;td&gt;
&lt;strong&gt;25,444 RPS&lt;/strong&gt; 🚀&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Avg Latency&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;29.13 ms&lt;/td&gt;
&lt;td&gt;22.83 ms&lt;/td&gt;
&lt;td&gt;
&lt;strong&gt;7.89 ms&lt;/strong&gt; ⚡&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Max Latency&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;2,000.00 ms ⚠️&lt;/td&gt;
&lt;td&gt;135.97 ms&lt;/td&gt;
&lt;td&gt;
&lt;strong&gt;93.27 ms&lt;/strong&gt; ✅&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Failed Requests&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;
&lt;strong&gt;60 (timeout)&lt;/strong&gt; 🔴&lt;/td&gt;
&lt;td&gt;0 ✅&lt;/td&gt;
&lt;td&gt;0 ✅&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h3&gt;
  
  
  💡 Analysis
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;🔴 Node's timeout failures:&lt;/strong&gt; The 60 failed requests with 2-second max latency strongly suggest GC pauses. This test should have been re-run with Node tuning flags (&lt;code&gt;--max-old-space-size&lt;/code&gt;, &lt;code&gt;--optimize-for-size&lt;/code&gt;) to determine if this is fundamental or tunable.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;🏆 Bun's single-core dominance:&lt;/strong&gt; Nearly double Go's throughput on a single core is impressive, but remember this is for a trivial 40-byte JSON response. Real applications doing actual work may show different patterns.&lt;/p&gt;




&lt;h2&gt;
  
  
  🚀 Phase 4: Cloud Multi-Core (4 Cores)
&lt;/h2&gt;

&lt;p&gt;Full resource allocation with clustering enabled for JavaScript runtimes.&lt;/p&gt;

&lt;h3&gt;
  
  
  🐳 Configuration
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker run &lt;span class="nt"&gt;--rm&lt;/span&gt; &lt;span class="nt"&gt;--cpus&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"4"&lt;/span&gt; &lt;span class="nt"&gt;-m&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"512m"&lt;/span&gt; &lt;span class="nt"&gt;-p&lt;/span&gt; 3000:3000 &lt;span class="o"&gt;[&lt;/span&gt;image]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  ⚔️ The Load Generator
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Attacker VM - wrk in Alpine container&lt;/span&gt;
docker run &lt;span class="nt"&gt;--rm&lt;/span&gt; alpine sh &lt;span class="nt"&gt;-c&lt;/span&gt; &lt;span class="s2"&gt;"apk add --no-cache wrk &amp;amp;&amp;amp; &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;&lt;span class="s2"&gt;
  wrk -t2 -c200 -d30s http://159.65.6.89:3000/json"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  📊 Results: Cloud 4-Core Maximum Throughput
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Metric&lt;/th&gt;
&lt;th&gt;Node.js&lt;/th&gt;
&lt;th&gt;Go&lt;/th&gt;
&lt;th&gt;Bun&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Throughput&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;31,025 RPS&lt;/td&gt;
&lt;td&gt;37,617 RPS&lt;/td&gt;
&lt;td&gt;
&lt;strong&gt;53,446 RPS&lt;/strong&gt; 🏆&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Total Requests (30s)&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;933,074&lt;/td&gt;
&lt;td&gt;1,130,171&lt;/td&gt;
&lt;td&gt;
&lt;strong&gt;1,605,818&lt;/strong&gt; 🎯&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Avg Latency&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;8.62 ms&lt;/td&gt;
&lt;td&gt;5.79 ms&lt;/td&gt;
&lt;td&gt;
&lt;strong&gt;4.04 ms&lt;/strong&gt; ⚡&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Max Latency&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;641.25 ms ⚠️&lt;/td&gt;
&lt;td&gt;218.91 ms&lt;/td&gt;
&lt;td&gt;
&lt;strong&gt;76.54 ms&lt;/strong&gt; ✅&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;CPU Usage&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;400%+&lt;/td&gt;
&lt;td&gt;340%&lt;/td&gt;
&lt;td&gt;383%&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h3&gt;
  
  
  💡 CPU Efficiency Deep Dive
&lt;/h3&gt;

&lt;p&gt;The raw CPU % numbers are misleading. What matters is &lt;strong&gt;CPU cost per request:&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;📊 Efficiency Ranking:
┌─────────────────────────────────────┐
│ Bun:  0.0072% CPU per request  🥇  │
│ Go:   0.0090% CPU per request  🥈  │
│ Node: 0.0129% CPU per request  🥉  │
└─────────────────────────────────────┘
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Calculation:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Node: 400% / 31k RPS = 0.0129% per request&lt;/li&gt;
&lt;li&gt;Go: 340% / 37.6k RPS = 0.0090% per request
&lt;/li&gt;
&lt;li&gt;Bun: 383% / 53.4k RPS = 0.0072% per request&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;💡 Key Insight:&lt;/strong&gt; Bun is genuinely the most efficient, but Node's higher absolute CPU usage just means all workers are busy—which is what you want under load.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;🤔 Go's "idle" CPU:&lt;/strong&gt; The 340% (leaving 60% unused) might indicate:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;GOMAXPROCS not set correctly&lt;/li&gt;
&lt;li&gt;Network socket polling leaving CPU headroom&lt;/li&gt;
&lt;li&gt;Or simply more efficient syscall handling&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  ⚖️ Code Architecture Comparison
&lt;/h2&gt;

&lt;h3&gt;
  
  
  🚨 Critical Difference: The Go Code is Heavily Optimized
&lt;/h3&gt;

&lt;p&gt;The Node and Bun code use default patterns, but the Go implementation uses production micro-optimizations:&lt;/p&gt;

&lt;h4&gt;
  
  
  Go optimizations applied:
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="n"&gt;jsonResponse&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="kt"&gt;byte&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;`{"message":"Hello from Go!"}`&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  &lt;span class="c"&gt;// Pre-rendered&lt;/span&gt;
&lt;span class="n"&gt;w&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Write&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;jsonResponse&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  &lt;span class="c"&gt;// Direct byte write, no JSON encoding&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Equivalent fair comparison would be:
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="c"&gt;// Fair comparison - same as Node/Bun pattern&lt;/span&gt;
&lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;NewEncoder&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;w&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Encode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;map&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s"&gt;"message"&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s"&gt;"Hello from Go!"&lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;⚠️ &lt;strong&gt;Impact:&lt;/strong&gt; This makes Go ~15-20% slower but tests equivalent functionality. The current benchmark favors Go's implementation.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h3&gt;
  
  
  🔍 Bun "Clustering" Isn't Actually Clustering
&lt;/h3&gt;

&lt;p&gt;The Bun code uses &lt;code&gt;reusePort: true&lt;/code&gt; in a &lt;strong&gt;single process&lt;/strong&gt;. This enables kernel-level socket load balancing but doesn't spawn multiple processes like Node's cluster module.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;For true architectural equivalence:&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="c1"&gt;// This is what would match Node's architecture&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;spawn&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="s2"&gt;bun&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;for &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;4&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="nf"&gt;spawn&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;bun&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="s2"&gt;server.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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;💡 &lt;strong&gt;Note:&lt;/strong&gt; The current test compares single-process Bun vs multi-process Node, which actually makes Bun's performance even more impressive but should be disclosed.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  🎯 What This Benchmark Actually Tells Us
&lt;/h2&gt;

&lt;h3&gt;
  
  
  ✅ Valid Conclusions
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;1. ⚡ Bun's event loop has lower per-request overhead than Node 
   for simple HTTP responses

2. 📈 Bun scales efficiently to multiple cores via kernel-level 
   socket distribution  

3. 🎯 Go provides predictable performance with excellent CPU 
   efficiency

4. 🌐 Network hardware matters more than runtime choice once 
   you hit I/O limits

5. 🔄 Node's cluster architecture has measurable IPC overhead 
   under high load
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  ❌ Invalid Conclusions
&lt;/h3&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;del&gt;"Bun is production-ready"&lt;/del&gt;&lt;br&gt;&lt;br&gt;
Speed ≠ ecosystem maturity, debugger support, APM tooling&lt;/p&gt;

&lt;p&gt;&lt;del&gt;"Node is slow"&lt;/del&gt;&lt;br&gt;&lt;br&gt;
This tests static JSON echo; database-heavy apps show different patterns&lt;/p&gt;

&lt;p&gt;&lt;del&gt;"Go is always better"&lt;/del&gt;&lt;br&gt;&lt;br&gt;
Developer productivity, ecosystem, and deployment complexity matter&lt;/p&gt;

&lt;p&gt;&lt;del&gt;"These numbers apply to my app"&lt;/del&gt;&lt;br&gt;&lt;br&gt;
Real apps do parsing, validation, DB queries, business logic&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  🔍 Limitations &amp;amp; What's Missing
&lt;/h2&gt;

&lt;h3&gt;
  
  
  ❌ Not Tested
&lt;/h3&gt;

&lt;p&gt;&lt;b&gt;Click to expand - What this benchmark doesn't cover&lt;/b&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Realistic payloads:&lt;/strong&gt; 10KB+ JSON parsing and validation&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Database I/O:&lt;/strong&gt; Connection pooling, query performance
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Memory pressure:&lt;/strong&gt; Behavior at 80%+ RAM utilization&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Sustained load:&lt;/strong&gt; 24-hour endurance, memory leaks&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Error handling:&lt;/strong&gt; Behavior under packet loss, slow clients&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Cold starts:&lt;/strong&gt; Container spin-up time (critical for serverless)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Long-tail latency:&lt;/strong&gt; p95, p99, p99.9 percentiles over hours&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  🔧 Methodological Improvements Needed
&lt;/h3&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;📊 Statistical rigor&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
5+ runs per config with statistical significance testing&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;🎯 Proper CPU pinning&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Use &lt;code&gt;--cpuset-cpus&lt;/code&gt; instead of &lt;code&gt;--cpus&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;⚙️ GC tuning for Node&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Test with optimized V8 flags&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;⚖️ Fair code comparison&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Either optimize all three or use stock patterns for all&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;🔄 Proper clustering for Bun&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Multi-process architecture to match Node&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  🎯 Production Recommendations
&lt;/h2&gt;

&lt;p&gt;Choose based on your actual constraints:&lt;/p&gt;

&lt;h3&gt;
  
  
  🐰 Use Bun if:
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;✅ You have existing Node.js code and want drop-in performance gains
✅ Your workload is I/O-heavy API routing/proxying
✅ You're comfortable with a newer ecosystem (risk tolerance)
⚠️  You can handle potential edge cases in package compatibility
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  🔷 Use Go if:
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;✅ You need predictable resource consumption for Kubernetes limits
✅ Your team values type safety and compile-time checks
✅ You're building infrastructure/platform services
✅ You need maximum efficiency per CPU core
✅ Long-term stability and tooling maturity matter
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  🟢 Use Node.js if:
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;✅ You have existing Node infrastructure and expertise
✅ Your bottleneck is database/external services (not event loop)
✅ Ecosystem maturity and package availability are critical
✅ You need battle-tested observability/APM tooling
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  💎 The Real Takeaway
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;For a 40-byte JSON echo server, Bun is measurably faster than Node.js.&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;But real applications aren't JSON echo servers. Your actual bottlenecks are probably:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;🗄️  Database query time
🌐  External API latency  
🧮  Business logic complexity
📡  Network infrastructure
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Profile your real workload before choosing a runtime based on microbenchmarks.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;That said, Bun's performance characteristics are impressive and worth evaluating for I/O-heavy services where event loop overhead matters.&lt;/p&gt;




&lt;h2&gt;
  
  
  📝 Full Code Listings
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Node.js (Clustered)
&lt;/h3&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;cluster&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;cluster&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;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;numCPUs&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;4&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;cluster&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;isMaster&lt;/span&gt;&lt;span class="p"&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;numCPUs&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="nx"&gt;cluster&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;fork&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="nx"&gt;cluster&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;worker&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="s2"&gt;`Worker &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;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;pid&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; died`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nx"&gt;cluster&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;fork&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;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;http&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;createServer&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="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;method&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;GET&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&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;/json&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;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;writeHead&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;200&lt;/span&gt;&lt;span class="p"&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;Content-Type&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;application/json&lt;/span&gt;&lt;span class="dl"&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="nx"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;stringify&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;message&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Hello from Clustered Node!&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="k"&gt;else&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;writeHead&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;404&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="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;}).&lt;/span&gt;&lt;span class="nf"&gt;listen&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;3000&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h3&gt;
  
  
  Bun (Single Process with reusePort)
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;Bun&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;serve&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;port&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;span class="na"&gt;reusePort&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="c1"&gt;// Kernel-level socket load balancing&lt;/span&gt;
  &lt;span class="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;request&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;url&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;URL&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;url&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;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;method&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;GET&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;pathname&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/json&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="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Response&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="nx"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;stringify&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;message&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Hello from Bun!&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;headers&lt;/span&gt;&lt;span class="p"&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;Content-Type&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;application/json&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="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;Response&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Not Found&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;status&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;404&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h3&gt;
  
  
  Go (Optimized - Not Fair Comparison)
&lt;/h3&gt;

&lt;p&gt;⚠️ &lt;strong&gt;This version pre-renders the response and skips JSON encoding&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;package&lt;/span&gt; &lt;span class="n"&gt;main&lt;/span&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="s"&gt;"fmt"&lt;/span&gt;
    &lt;span class="s"&gt;"net/http"&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c"&gt;// Pre-rendered response eliminates JSON encoding overhead&lt;/span&gt;
&lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="n"&gt;jsonResponse&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="kt"&gt;byte&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;`{"message":"Hello from Go!"}`&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;jsonHandler&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;w&lt;/span&gt; &lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ResponseWriter&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;r&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Request&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="n"&gt;r&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Method&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;MethodGet&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;w&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;WriteHeader&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;StatusMethodNotAllowed&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="n"&gt;w&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Header&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Content-Type"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"application/json"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;w&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Write&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;jsonResponse&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c"&gt;// Note: Ignoring error - not production-safe&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;server&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Server&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;Addr&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;    &lt;span class="s"&gt;":3000"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;Handler&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;HandlerFunc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;jsonHandler&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Go server running on port 3000"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;server&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ListenAndServe&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;h3&gt;
  
  
  Go (Fair Comparison - Uses JSON Encoding)
&lt;/h3&gt;

&lt;p&gt;✅ &lt;strong&gt;This version matches Node/Bun's approach&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;package&lt;/span&gt; &lt;span class="n"&gt;main&lt;/span&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="s"&gt;"encoding/json"&lt;/span&gt;
    &lt;span class="s"&gt;"net/http"&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="n"&gt;Response&lt;/span&gt; &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;Message&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="s"&gt;`json:"message"`&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;jsonHandler&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;w&lt;/span&gt; &lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ResponseWriter&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;r&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Request&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="n"&gt;r&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Method&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;MethodGet&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;w&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;WriteHeader&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;StatusMethodNotAllowed&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="n"&gt;w&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Header&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Content-Type"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"application/json"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;NewEncoder&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;w&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Encode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Response&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;Message&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s"&gt;"Hello from Go!"&lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;HandleFunc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"/json"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;jsonHandler&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ListenAndServe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;":3000"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;nil&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;h2&gt;
  
  
  🙏 Acknowledgments
&lt;/h2&gt;

&lt;p&gt;Thanks to the readers who will inevitably point out additional issues I missed. Benchmarking is hard, and there's always room for improvement.&lt;/p&gt;

&lt;p&gt;If you want to reproduce these tests or improve the methodology, feel free to reach out!&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;Found this useful? Drop a ❤️ and let me know what you'd like to see benchmarked next!&lt;/strong&gt;&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>javascript</category>
      <category>bunjs</category>
      <category>go</category>
    </item>
  </channel>
</rss>
