Node.js vs Golang: Memilih Senjata Utama untuk Microservices
Konteks: Microservices dalam Dunia Nyata
Dalam 3 tahun pengalaman saya sebagai Fullstack Developer di Bali, saya membangun microservices dengan kedua stack: Node.js (Express/Fastify) dan Go (net/http, Fiber). Keduanya memiliki kekuatan masing-masing, dan memilih yang "terbaik" bergantung pada konteks problem Anda.
Artikel ini bukan perang framework — ini analisis objektif dengan data nyata.
Performa: Siapa yang Lebih Cepat?
Benchmark Sederhana: Hello World Endpoint
| Metric | Node.js (Fastify) | Go (net/http) |
|---|---|---|
| Requests/sec | ~28.500 | ~52.000 |
| Latency rata-rata | 3.5ms | 1.9ms |
| Memory usage | 45MB | 11MB |
| Binary/Deployment size | 85MB (node_modules) | 8.5MB |
Go menang di semua metric. Tetapi mari kita dalam ke real-world scenario.
Real-World: API dengan DB Query + JSON Serialization
| Metric | Node.js | Go |
|---|---|---|
| Requests/sec (10 RPS) | 9.800 | 14.200 |
| Requests/sec (100 RPS) | 8.300 | 13.800 |
| Requests/sec (500 RPS) | 6.100 ⚠️ | 12.900 |
| CPU usage saat peak | 85% | 45% |
| Memory leak setelah 1 jam load | Ya (perlu restart) | Tidak |
Saat beban tinggi, Node.js mengalami degradation karena event loop blocking. Go tetap stabil karena goroutines.
Concurrency Model
Node.js: Single-Threaded Event Loop
// Node.js - blocking operasi mempengaruhi semua request
app.get('/heavy', async (req, res) => {
// Jika ini blocking, semua request lain menunggu
const result = heavyComputation(); // 🚫 Block event loop!
res.json(result);
});
// Solusi: gunakan Worker Threads
const { Worker } = require('worker_threads');
app.get('/heavy', (req, res) => {
const worker = new Worker('./heavy-task.js');
worker.on('message', result => res.json(result));
});
Go: Goroutines
// Go - concurrency natural dengan channel
func handler(w http.ResponseWriter, r *http.Request) {
ch := make(chan Result)
go func() {
// Akan dijadwalkan secara preemptive
result := heavyComputation()
ch <- result
}()
result := <-ch
json.NewEncoder(w).Encode(result)
}
// 1000 goroutines? Biaya hanya ~4KB per goroutine
for i := 0; i < 1000; i++ {
go processRequest(i)
}
Verdict: Go menang telak di concurrency. Node.js butuh workaround (worker_threads), dan overhead-nya signifikan.
Ekosistem & Developer Experience
Node.js: Library untuk Semua
Keunggulan paling strong Node.js adalah ekosistem npm — ada paket untuk hampir semua use case:
# Akses 2 juta+ packages
npm install express prisma bull bullmq socket.io redis rate-limiter-flexible helmet sharp
- TypeScript support yang mature: tipe tersedia otomatis untuk sebagian besar package.
Go: Library yang Terkonsentrasi
# Library jumlahnya lebih sedikit tapi stable
go get github.com/gin-gonic/gin
go get gorm.io/gorm
go get github.com/redis/go-redis/v9
- Kualitas library Go cenderung tinggi (kontribusi enterprise: Google, Uber, Cilium)
- Versi stabil: jarang breaking change karena stdlib yang solid
- Tapi solusi spesifik (misal: PDF generator, video processing) lebih terbatas
Kecepatan Development
| Aspek | Node.js | Go |
|---|---|---|
| Setup project | 5 menit | 10 menit |
| Hot reload | ✅ nodemon instant |
⚠️ air agak lambat |
| Iterasi feature | Cepat (dynamic) | Lambat (type checking) |
| Debugging | Chrome DevTools (luar biasa) | Delve + dlv (cukup) |
| Test writing | Cepat (jest/sinon) | Agak verbose (stdlib) |
Node.js jauh lebih cepat untuk MVP development. Go unggul di maintenance phase.
Deployment: Binary vs Runtime
Node.js Deployment
FROM node:20-alpine
COPY package*.json ./
RUN npm ci --production
COPY . .
EXPOSE 3000
CMD ["node", "server.js"]
# Size: ~200MB, butuh Node.js runtime di image
Go Deployment
FROM golang:1.22 AS builder
COPY . .
RUN go build -o server cmd/server/main.go
FROM scratch
COPY --from=builder /app/server /server
CMD ["/server"]
# Size: ~8MB, tidak butuh apapun!
Decision Matrix
| Pilih Node.js jika... | Pilih Go jika... |
|---|---|
| Tim Anda full JavaScript | Butuh konkurensi paralel (1000+ RPS) |
| MVP perlu cepat launching | Binary distribution penting (IoT, CLI) |
| Banyak integration 3rd party SDK | Memory footprint harus minimal |
| Real-time (WebSocket heavy) | Reliability untuk long-running service |
| Ekosistem npm krusial | Slow startup harus dihindari |
Kesimpulan
Saya pribadi menggunakan keduanya sesuai need:
- Node.js: untuk API yang butuh library eksternal banyak (payment SDK, social media API, video processing) dan timeline pengembangan cepat
- Go: untuk service inti yang high-throughput (authentication gateway, message queue worker, internal API)
Tidak ada pemenang absolut — pilih sesuai kebutuhan, bukan sesuai hype.