DEV Community

Cover image for 🔬 NestJS vs Go: Performance Benchmark (Do you really need to migrate?)
Tomás Alegre Sepúlveda
Tomás Alegre Sepúlveda

Posted on

🔬 NestJS vs Go: Performance Benchmark (Do you really need to migrate?)

🇪🇸 Lee este post en Español

Hello everyone. I recently conducted an exhaustive benchmark to answer a classic question in backend teams: does it make sense to migrate to Go, or is NestJS enough?

There is no magic answer, but data helps decide. Here is a summary of the most important findings.


🏗️ The Scenario

I compared two typical architectures running in Docker on the same machine (M4 Pro):

  1. NestJS (Node 22) + Prisma v6 (Productivity approach)
  2. Go (1.24) + GORM (Performance approach)

Both connected to PostgreSQL 15 and subjected to stress tests (gRPC and HTTP) simulating a real environment.


🧪 Methodology: What did we measure?

To truly understand the differences, I divided the tests into two key scenarios:

  1. Small Data (1x1 Insert):
    Simulates typical transactional traffic of a REST/gRPC API. We receive an object, validate it, and save it. Here we measure the framework's base latency.

  2. Large Data (Batch Insert of 1000 elements):
    Simulates bulk load processes, ETLs, or event ingestion. We send arrays of 1000 objects that must be deserialized, validated, and saved in a single transaction. This is where CPU and Garbage Collector suffer the most.


📊 The Results

1. Small Data: The Surprise

In low load or unit insert scenarios, the difference was minimal. Go obtained a latency improvement of just ~10% over NestJS.

Conclusion: For standard CRUD operations, NestJS is incredibly efficient, and the performance difference rarely justifies losing TypeScript's productivity.

2. Large Data: The Breaking Point

The story changes drastically when processing massive batches (arrays of 1000 elements) under high concurrency.

Scenario: 100 RPS constant (Bulk Inserts)

Service Real Throughput P95 Latency Success Rate
Go gRPC 85 RPS 71.88 ms 100%
NestJS gRPC 78 RPS 98.44 ms ~85%

What happened here?

  1. Serialization: Node.js (V8) has a higher cost when serializing/deserializing large volumes of JSON compared to Go Structs and Protobuf.
  2. Connection Pool: Under extreme pressure, the Prisma connection pool started to saturate (P2024 errors), causing NestJS to lose ~15% of requests.
  3. Stability: Go maintained 100% success and more predictable latencies, thanks to its goroutine management and a more efficient GC for this type of load.

⚖️ Conclusion: When to use which?

Based on the data, here is my pragmatic recommendation:

✅ Stay with NestJS if:

  • You are building an MVP or validating a product.
  • Your team already knows TypeScript and you value development speed.
  • The load is moderate (< 300 RPS) and standard CRUD operations (Small Data).
  • BFF (Backend for Frontend): If you only need to orchestrate calls to a few services and the serialization load is low.

🚀 Migrate to Go if:

  • Complex BFF: If your BFF needs to call many microservices, add heavy logic, serialize large volumes of data, and perform massive fan-out, Go will handle concurrency much better.
  • Your system constantly performs massive Bulk Operations / ETL (Large Data).
  • You need to handle thousands of concurrent connections (e.g., Gateways, massive Websockets).
  • You have very strict latency SLAs where Node's Garbage Collector spikes are unacceptable.
  • Infrastructure is expensive and you need to squeeze every CPU cycle.

📖 Read the full analysis

This post is a summary. The detailed analysis (with all tables, charts, hardware configuration, and error analysis) is public and free.

👉 Read the full article on Buy Me a Coffee

💻 View code on GitHub


💌 Special Acknowledgments

To a girl who, without knowing it, pushed me to keep creating and programming in my free time. To the one who was once my spark: for "YLP", with gratitude... and with scars that also teach.


If you find this analysis useful, any feedback is welcome!

Top comments (0)