Skip to content

DeepeshKalura/go-vs-node-benchmark

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

4 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Go vs. Node.js: A Stress Test of Pure, Unfiltered Chaos

This isn't just another benchmark. This is a demonstration of a philosophy: Data over dogma. Rigorous testing over "trust me, bro" metrics. I'm Deepesh Kalura, and this is the story of how I pushed Go and Node.js to their absolute breaking points to uncover the truth about performance and cost.

Project Banner


My Motivation: The Problem with Vanity Benchmarks

This whole project started with a LinkedIn post. You've probably seen them: astronomical claims of "20,000 requests/second," declaring one language "crushes" another based on a 30-second drag race.

I saw those numbers and felt... nothing. They lacked context, rigor, and reality.

So, I decided to do it right. My goal wasn't just to see which was faster; it was to build a proper arena, apply merciless and observable stress, and find the true breaking point of each system. I wanted to analyze the wreckage to understand why it broke and what that means for real-world architectural decisions.

The Arena: My Blueprint for a Proper Engineering Coliseum

To do this right, you need more than a script. You need a controlled, observable, and reproducible environment. I defined the entire testbed using Docker Compose. This is how you get reliable data.

My arena contains:

  • The Contenders: A Node.js/Express app and a Go app, both with the same simple task: fetch 200 documents from a database.
  • A Real Workload: A MongoDB container, pre-loaded with 5,000 documents. No empty variables.
  • The Observability Stack (This is non-negotiable):
    • k6: My virtual army, simulating thousands of concurrent users with complex, staged load profiles.
    • Prometheus & cAdvisor: My data spies, scraping deep resource metrics (CPU, Memory, I/O) from every container.
    • Grafana: My command center, where I watched the battle unfold in real-time.

To make the fight fair, I strictly limited each application to 1.0 CPU cores and 512MB of RAM.


Recreate the Chaos: Run It Yourself

Prerequisites: Docker and Docker Compose.

1. Launch the Environment

This single command brings the entire stack to life.

docker compose up -d

2. Unleash the Stress Test

Target the application you want to push to its limits.

To Stress Test Node.js:

docker-compose run k6-tester run /scripts/script.js -e TARGET_URL=http://node-app:3000 --out experimental-prometheus-rw

To Stress Test Go:

docker-compose run k6-tester run /scripts/script.js -e TARGET_URL=http://go-app:3001 --out experimental-prometheus-rw

3. Watch the Battle Live

  • Grafana Dashboard: http://localhost:3000 (user: admin, pass: admin)
  • cAdvisor Container Metrics: http://localhost:8088
  • Prometheus Raw Data: http://localhost:9090

The Data-Driven Story: My Findings

I didn't just run one test; I ran a series of experiments designed to tell a story.

  • Act I: The Baseline (250 Users): Go was faster, but the real story was that Node.js was already using 90% of its CPU just to keep up, while Go was coasting at 60%. The bottleneck wasn't the database; it was the CPU.
  • Act II: The First Cracks (500 Users): Here, Node.js failed. Its response times skyrocketed. Go's CPU hit 100%, but it bent without breaking, still meeting performance targets. I had found the performance ceiling for Node.js on this hardware.
  • Act III: Catastrophic Failure (10,000 Users): This is where the most valuable insights emerged.
    • Go failed by brute force, dropping 50% of requests with a 25-second response time and consuming nearly 400MB of RAM.
    • Node.js had a more "graceful" collapse, dropping fewer requests (37%) with a 5-second response time and using only half the memory (~200MB).

The Ultimate Conclusion: Performance Engineering is About Business, Not Feelings

This journey led to truths that are far more valuable than a simple "Go is faster" headline.

  1. Your Bottleneck is Never Where You Assume: I proved this was a CPU-bound JSON serialization problem, not a database I/O problem. This insight is critical for optimization.
  2. Benchmark for Failure, Not Just for Speed: The most valuable data comes from the wreckage. Understanding how your system breaks is how you build resilient, predictable applications.
  3. Efficiency Isn't Just Speed; It's Cost: This is the bottom line. Go's raw performance per core means you need fewer machines to handle the same load. My final estimate showed the Go solution would be roughly 30% cheaper to operate at scale.

This is the power of true performance engineering. It's about translating technical characteristics into architectural decisions and, ultimately, dollars and cents.


About Me & Let's Connect

I'm Deepesh Kalura. I'm a man in internet who is communicate with computers passionate about building resilient, efficient, and cost-effective systems by replacing assumptions with hard data.

If you're building systems where performance translates directly to your monthly cloud bill, or if you simply believe in this data-driven approach to engineering, let's talk.

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Contributors 3

  •  
  •  
  •