Back to News/Why I Ditched Rust, Node, and Python for Go: The Brutally Honest Benchmark Data

Why I Ditched Rust, Node, and Python for Go: The Brutally Honest Benchmark Data

A head-to-head benchmark of 7 popular programming languages: performance, memory, concurrency, developer experience, and the hiring market. Discover exactly why Go dominates production at millions of requests — and why I almost jumped ship to Rust (but didn't).

Faisal Affan
3/1/2026
Why I Ditched Rust, Node, and Python for Go: The Brutally Honest Benchmark Data — 1 / 4
1 / 4

Why I Choose Go as My Primary Stack

"Simplicity is the ultimate sophistication." — Leonardo da Vinci

Disclaimer

This article is not about "Go is the best language ever" — but rather about why Go is perfectly suited as a primary stack for my context and needs, and why I remain open to other stacks. All programming languages are tools — choose the right one for the right problem.


🎯 1. The Decision

Every engineer inevitably hits this point: choosing a primary stack. It doesn't mean shutting yourself off from other technologies, but defining one language as your "home base" — the place where you are most productive, understand the ecosystem the deepest, and are most confident in delivering production-grade software.

Cross-Stack Experience

Years of working with PHP, Python, Node.js, Java, Dart — eventually experimenting with Rust and .NET across various project scales.

Production-Proven

Choosing Go wasn't based on hype, but on real-world experience building and operating systems in production.

Pragmatism Over Fanaticism

Choosing Go as my primary doesn't mean I close myself off. I still use TypeScript, Python, Dart, and other languages as needed.

After years of working with various languages, I chose Go (Golang) as my primary stack. Here are the reasons, complete with benchmark data.


📊 2. Benchmark: Go vs The Rest

Compilation Speed

One of the first things that made me fall in love with Go: blazing fast compilation.

LanguageCompile TimeNotes
Go~2-5 secondsIncremental, extremely fast
Rust~30-120 secondsBorrow checker + heavy optimization
Java~10-30 secondsSeparate JIT warmup
.NET (C#)~5-15 secondsDecent, but still loses out
TypeScript (Node)~5-20 seconds (tsc)Depends on config & size
PHPN/A (interpreted)No compile step
PythonN/A (interpreted)No compile step

Why So Fast?

Go was designed from the ground up to compile fast. Rob Pike and the Google team built Go because they were frustrated by C++ compile times that could reach 45 minutes in Google's monorepo. Go's dependency resolution is linear — not exponential like C/C++.

Memory Efficiency

This is critical for production — especially when running dozens of microservices on Kubernetes.

Language/RuntimeMemory Usage (Idle)Relative to Go
Go~8-12 MB1x (baseline)
Rust~2-5 MB0.4x (winner)
PHP (Laravel)~20-40 MB/worker3x
Node.js~30-50 MB4x
Python (FastAPI)~30-50 MB4x
.NET (ASP.NET)~50-100 MB8x
Java (Spring Boot)~150-300 MB25x
Language/RuntimeMemory Under LoadRelative to Go
Go~20-50 MB1x (baseline)
Rust~10-30 MB0.5x (winner)
PHP (Laravel)~50-100 MB/worker3x
Node.js~80-200 MB4x
Python (FastAPI)~80-200 MB4x
.NET (ASP.NET)~100-300 MB6x
Java (Spring Boot)~300-800 MB12x

The Sweet Spot

Rust indeed wins in memory, but Go provides the best balance between memory efficiency and ease of development. You get ~90% of Rust's efficiency with ~30% of the effort.

HTTP Request Throughput

Benchmark using a simple JSON response scenario ({"message": "hello"}):

Language/FrameworkRequests/secAvg Latency
Rust (Actix-web)~650,000~0.15ms
Go (Fiber)~550,000~0.18ms
Go (net/http)~450,000~0.22ms
.NET (ASP.NET Minimal)~350,000~0.28ms
Java (Spring WebFlux)~300,000~0.33ms
Node.js (Fastify)~150,000~0.67ms
PHP (Swoole)~120,000~0.83ms
Python (uvicorn)~40,000~2.5ms

Cold Start Time

Crucial for serverless and container-based deployments:

Serverless & Kubernetes

In the era of serverless and Kubernetes, cold start time is no trivial matter. Go and Rust lead by a massive margin here because they compile down to a static binary with no runtime dependencies. Java, with its 3.5 second cold start, can be a showstopper for serverless workloads.

Binary Size & Deployment

LanguageBinary/Artifact Size
Rust~5-10 MB
Go~10-15 MB
Java~30-80 MB (JAR)
.NET~30-60 MB
Python~30-100 MB (venv)
PHP~50-150 MB (vendor)
Node.js~50-200 MB (node_modules)
LanguageDocker Image Size
Rust~10-15 MB (scratch)
Go~15-20 MB (scratch)
PHP~100-200 MB
.NET~150-250 MB
Node.js~150-300 MB
Java~200-400 MB
Python~150-400 MB

Go outputs a single static binary — no runtime needed, no dependency managers required in production:

Dockerfile
FROM scratch
COPY myapp /app
ENTRYPOINT ["/app"]

That's it. A 15 MB Docker image. Compare that to Node.js which requires a node_modules folder sitting at 200 MB.


⚡ 3. Beyond Numbers: Why Go Wins for Me

Benchmarks are only half the story. Here are the qualitative factors that make Go my top choice:

Simplicity by Design

25 keywords. No generics abuse, no annotation magic, no hidden behavior. What you see is what you get.

Concurrency First-Class

Goroutines + Channels = Elegant concurrency. ~2-8 KB per goroutine vs ~1 MB per thread in Java.

Standard Library

net/http, encoding/json, database/sql, crypto, testing — all production-ready without third-party dependencies.

Tooling Excellence

go fmt, go vet, go test, go mod, go build — built-in, integrated, no config hell.

Simplicity by Design

main.go
package main

import (
    "fmt"
    "net/http"
)

func main() {
    http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
        fmt.Fprintf(w, `{"message": "Hello, World!"}`)
    })
    http.ListenAndServe(":8080", nil)
}

10 lines. No annotations, no DI frameworks, no XML configs.

HelloController.java
package com.example.demo;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

@SpringBootApplication
@RestController
public class DemoApplication {
    public static void main(String[] args) {
        SpringApplication.run(DemoApplication.class, args);
    }

    @GetMapping("/")
    public String hello() {
        return "{\"message\": \"Hello, World!\"}";
    }
}

Plus a pom.xml / build.gradle, application.properties, and a deep dependency tree.

index.js
const express = require("express");
const app = express();

app.get("/", (req, res) => {
  res.json({ message: "Hello, World!" });
});

app.listen(8080, () => console.log("Server running"));

Plus package.json, node_modules/ (~200 MB), and package-lock.json.

Concurrency: Goroutines vs Threads

concurrency.go
// Goroutines + Channels = Elegant concurrency
func processOrders(orders []Order) []Result {
    results := make(chan Result, len(orders))

    for _, order := range orders {
        go func(o Order) {
            results <- processOrder(o)
        }(order)
    }

    var processed []Result
    for range orders {
        processed = append(processed, <-results)
    }
    return processed
}

1 Million Concurrent Connections

Goroutines use only a ~2-8 KB stack (vs ~1 MB per thread in Java/.NET). This means you can run millions of concurrent goroutines in a single process — using the same amount of memory Java would need for just ~50 threads.

Built-in Tooling

Prop

Type

Need to cross-compile from a Mac to Linux?

Terminal
GOOS=linux GOARCH=amd64 go build -o myapp

Done. No Docker dependencies, no VMs, no convoluted CI pipelines needed.

Clean Project Structure

main.go
go.mod
go.sum
Dockerfile

There is no node_modules/, no 200 MB vendor/ folder, no config hell. It's clean, predictable, and easy to navigate.


🔍 4. Where Others Shine: Honest Comparison

Choosing Go doesn't mean blinding myself to the strengths of other languages. Every language has its own sweet spot:


🧠 5. My Stack Philosophy

Core Principle

"Use the right tool for the right job." — Every single programming language is a tool. A carpenter doesn't just hold a hammer — they own saws, drills, chisels, and sandpaper. They each serve their own unique, specific purpose.

Decision Framework

How I select a stack for any given project:

My Toolbox

🐹 Primary — Go (90% Backend Work)

API services, microservices, CLI tools, infrastructure tooling, system programming. Go seamlessly handles 90% of my backend needs with absolutely staggering efficiency.

⚛️ Frontend — TypeScript + React/Next.js

Undeniably the best ecosystem for modern UI. Flawless type safety, clean component-based architectures, and an overwhelmingly massive community.

📱 Mobile — Flutter/Dart

Cross-platform, utilizing a single codebase. Delivering near-native performance while keeping development speeds at an absolute high.

🐍 Data & ML — Python

The absolute king of machine learning, data pipelines, and scripting. There is simply no better alternative for this specific domain.

🦀 Performance-Critical — Rust

When Go simply isn't fast enough — for embedded hardware, WASM, or extraordinarily compute-heavy components.

The 80/20 Rule

Go reliably handles 80% of my needs with exactly 20% of the complexity. That is an absolutely flawless sweet spot. The second I need something far beyond what Go offers natively, I swap to the right tool — without ego, and completely without fanatical brand loyalty.


📈 6. Real-World Impact

A few metrics sourced from live production systems I personally built using Go:

MetricBefore (Node.js/PHP)After (Go)Improvement
Response Time (p99)~250ms~15ms16x faster
Memory per Instance~512 MB~50 MB10x less
Docker Image Size~350 MB~18 MB19x smaller
Cold Start~3s~10ms300x faster
Monthly Infra Cost~$500~$806x cheaper

Cost Impact

The numbers presented above are sourced directly from real-world production experiences. Go's extreme resource efficiency directly translates to truly significant infrastructure cost savings. If you run 20+ microservices, a differential of ~460 MB of memory per instance essentially means you can run 10x the number of services on exactly the same hardware.


🏁 7. Conclusion

TL;DR

Choosing Go isn't about calling other languages bad. All programming languages are simply tools — and the great tools are chosen strictly based on needs, zero fanaticism allowed.

Go became my permanent primary stack because it delivers:

Unmatched Simplicity Built on only 25 keywords. Flawless code that is

profoundly readable, maintainable, and highly debuggable by anyone on the team.

First-Class Concurrency Using Goroutines + Channels. Pushing millions of

concurrent connections gracefully with minimal memory overhead.

Effortless Deployment Generating exactly one single static binary.

COPY and you are done. An impossibly lean 15 MB Docker image.

Incredible Cost Efficiency Providing resource efficiency that directly

and powerfully translates to rapid infrastructure cost savings — bringing everything down to 6x cheaper in production.

Yet I still write TypeScript for the frontend, Dart on mobile, Python for complex data workflows, and I fully remain open to deploying Rust for use cases that require absolutely monstrous performance.

The absolute best language is the one that solves your problem effectively. Go just happens to be that exact language for the vast majority of my work. And I will never hesitate to switch layers when the context aggressively demands it.

Because ultimately, we aren't "Go developers" or "Java developers" — we are engineers who wield the best tools available to solve incredibly specific problems.


Related Articles

Why I Ditched Rust, Node, and Python for Go: The Brutally... | Faisal Affan