Ambil contoh service notifikasi yang mengirim push notification dan template WhatsApp untuk sekitar dua juta pengguna. Kalau ditulis di Node.js, service seperti ini biasanya berakhir di lima atau enam container dengan memori beberapa ratus megabyte per container. Kalau ditulis ulang di Go, beban yang sama sering cukup dengan dua container di bawah 100 MB. Kelihatannya Go menang telak, dan untuk service jenis itu biasanya memang iya. Tapi API dashboard pelanggan yang ada di sebelahnya sering lebih baik dibiarkan di NestJS. Berikut cara kami menimbang pilihan ini.
Perbandingan Singkat
| Aspek | Go | Node.js |
|---|---|---|
| Concurrency | Goroutine dibagi ke semua core CPU oleh runtime | Satu event loop per proses, perlu worker_threads atau proses tambahan untuk core lain |
| Memori saat idle per instance | Biasanya 10 sampai 30 MB | Biasanya 50 sampai 100 MB sebelum kode Anda bekerja banyak |
| Pekerjaan berat di CPU | Aman, berjalan paralel | Menahan event loop kalau tidak dipindah dari main thread |
| Tipe data | Static type yang dicek compiler, selalu aktif | TypeScript di atas JavaScript, seketat konfigurasi tsconfig Anda |
| Hasil build | Satu binary, image 10 sampai 25 MB itu wajar | Runtime plus node_modules, image 150 MB ke atas itu wajar |
| Ekosistem | Standard library kuat, package lebih sedikit tapi stabil | npm punya package untuk hampir semua hal, kualitasnya beragam |
| Cari developer di Indonesia | Lebih sedikit, kebanyakan level menengah dan senior | Sangat banyak, junior mudah dicari |
Performa dan Pemakaian Memori
Untuk pekerjaan I/O biasa, misalnya API yang membaca PostgreSQL lalu mengembalikan JSON, selisihnya lebih kecil dari yang terlihat di benchmark. V8 itu cepat, dan sebagian besar waktu habis untuk menunggu database. Service Fastify yang ditulis dengan rapi dan service Go dengan net/http sama-sama bisa melayani beberapa ribu request per detik per core untuk endpoint semacam itu.
Perbedaannya muncul di dua tempat. Pertama, memori. Proses Go mulai dari ukuran kecil dan pemakaiannya stabil, dan ini terasa kalau Anda bayar per container atau jalan di VPS kecil. Kedua, latensi di ekor distribusi saat beban tinggi. Go membagi kerja ke semua core dalam satu proses, dan garbage collector-nya biasanya berhenti jauh di bawah satu milidetik. Proses Node hanya memakai satu core untuk JavaScript, jadi satu request yang lambat bisa membuat request lain di proses itu ikut menunggu.
Goroutine dan Event Loop
Node menjalankan JavaScript Anda di satu thread. I/O jaringan dan file diserahkan ke sistem operasi atau libuv, lalu callback kembali ke loop saat hasilnya siap. Model ini efisien selama tidak ada kode di main thread yang makan waktu lama. Masalahnya sering datang dari kode yang kelihatan aman. JSON.parse untuk payload 20 MB, bcrypt versi sinkron, regex yang ditulis asal, atau loop di seratus ribu baris data akan membekukan semua request di proses itu sampai selesai.
Go mengambil jalan sebaliknya. Setiap request jalan di goroutine sendiri dengan stack awal beberapa kilobyte, dan scheduler membagi ribuan goroutine ke thread OS di semua core. Anda menulis kode blocking biasa, runtime yang mengurus proses menunggunya. Request yang lambat hanya memperlambat dirinya sendiri. Sejak Go 1.25, runtime juga membaca batas CPU container saat mengatur GOMAXPROCS, jadi di Kubernetes perilakunya masuk akal tanpa tuning tambahan. Konsekuensinya, paralelisme ini nyata, jadi data race harus dipikirkan. Kebiasaan untuk mencegahnya sudah kami bahas di artikel concurrency Go.
Tipe Data Go dan TypeScript
Sekarang hampir tidak ada tim yang menulis JavaScript polos di backend, jadi perbandingan yang adil adalah Go melawan TypeScript. Sistem tipe TypeScript lebih kaya. Union type, generic dengan conditional type, dan inferensinya membuat kode sangat ekspresif. Go lebih sederhana, dan sebagian orang merasa kodenya berulang, terutama pengecekan if err != nil.
Di service yang umurnya panjang, kesederhanaan itu justru membantu. Tipe TypeScript hilang saat runtime, jadi data dari request body atau API pihak ketiga hanya seaman validasi Anda dengan Zod atau class-validator. Tipe any gampang menyusup, dan strict mode sering dimatikan di proyek lama. Di Go, compiler mengecek semuanya, formatter-nya cuma satu, dan kode dari developer baru bentuknya mirip dengan kode tech lead. Node versi baru sudah bisa menjalankan file .ts langsung dengan membuang tipenya, tapi Anda tetap butuh tsc di CI supaya tipenya benar-benar dicek.
Ekosistem dan Cari Developer di Indonesia
JavaScript adalah bahasa yang paling banyak dipelajari developer Indonesia di awal karier, lewat bootcamp, tugas kampus, dan kerjaan frontend. Cari developer Node.js di Bandung atau Jakarta cukup beberapa hari. Go populer di sini terutama karena Gojek, Tokopedia, dan perusahaan teknologi besar lain, jadi engineer Go biasanya sudah menengah atau senior, dan gajinya lebih tinggi. Kalau Anda perlu menambah tim dengan cepat dan banyak junior, Node lebih mudah.
Soal library, npm menang di jumlah. Ada SDK untuk hampir semua payment gateway, layanan SaaS, dan format file yang aneh-aneh. Package Go lebih sedikit, tapi standard library-nya sudah mencakup HTTP, JSON, kriptografi, template, dan testing dengan baik. Sejak Go 1.22, net/http mendukung method dan parameter path di routing, jadi banyak service tidak lagi butuh Gin atau Echo. Dependency yang lebih sedikit juga berarti lebih jarang dapat kejutan security advisory yang harus di-patch.
Deploy dan Operasional
Service Go di-build jadi satu binary. Anda bisa menaruhnya di image distroless, mengirimnya ke server pakai scp, atau menjalankannya sebagai systemd unit. Cross compile ke Linux dari Mac cukup dengan satu environment variable. Service Node butuh runtime, lockfile, dan node_modules yang sering berukuran ratusan megabyte sebelum dipangkas. Docker memang menutupi sebagian besar repotnya, tapi ukuran image tetap berpengaruh ke waktu pull, cold start, dan biaya registry. Di sisi lain, Node memberi feedback lokal yang lebih cepat lewat hot reload, dan hampir semua PaaS mendukungnya tanpa konfigurasi.
Cara Kami Memutuskan
- Pilih Node.js kalau tim sudah kuat di TypeScript, frontend-nya Next.js atau React sehingga tipe bisa dipakai bersama, dan service-nya kebanyakan CRUD di atas database.
- Pilih Node.js kalau Anda butuh banyak SDK pihak ketiga dan kecepatan rilis lebih penting daripada biaya server.
- Pilih Go untuk service dengan concurrency tinggi, seperti gateway, server WebSocket, worker antrean, dan service yang memanggil banyak service lain sekaligus.
- Pilih Go kalau memori per instance menentukan tagihan cloud, atau kalau ada kerja berat di CPU seperti olah gambar, generate PDF, atau enkripsi di jalur request.
- Pilih Go untuk CLI dan agent internal yang harus jalan di banyak mesin tanpa install runtime.
Pakai Keduanya Itu Wajar
Banyak tim yang kami bantu akhirnya memakai keduanya, dan itu berjalan baik. Pola yang sering kami pakai: frontend Next.js dan API NestJS atau Express di depan pengguna, lalu service Go di belakangnya untuk bagian yang berat. Keduanya ngobrol lewat HTTP dengan kontrak OpenAPI, atau lewat gRPC kalau latensi jadi perhatian. Kalau Anda mau ke arah ini, beberapa aturan berikut membuatnya tetap rapi.
- 1Profiling dulu. Cari endpoint atau job yang benar-benar bermasalah dengan clinic.js atau Node inspector sebelum memutuskan apa yang dipindah.
- 2Pindahkan satu bagian yang batasnya jelas, misalnya generator laporan atau consumer webhook, dan pertahankan kontrak API-nya supaya pemanggil tidak perlu berubah.
- 3Jalankan versi lama dan baru berdampingan selama seminggu, lalu bandingkan latensi, error rate, dan biayanya.
- 4Pakai satu format log dan satu setup tracing dengan OpenTelemetry supaya satu request bisa ditelusuri lintas bahasa.
Menulis ulang service Node yang sudah jalan ke Go hanya karena Go lebih cepat jarang sepadan. Memindahkan satu jalur panas yang bikin boros biaya biasanya sepadan.
Kami membangun dan merawat backend dengan kedua bahasa ini. Pelatihan Golang kami juga sering diikuti tim Node.js yang ingin memindahkan satu atau dua service ke Go tanpa menghentikan pengerjaan fitur. Kalau tim Anda sedang di posisi itu, kami senang ngobrol soal service mana yang paling masuk akal untuk dimulai.
Poin penting
- Untuk API sederhana berbasis database, selisih kecepatan Go dan Node.js kecil, dan Go paling unggul di pemakaian memori.
- Node menjalankan JavaScript di satu thread per proses, jadi kode berat di CPU pada jalur request memperlambat semua request lain.
- Tipe di Go dicek saat compile dan selalu aktif, sedangkan keamanan TypeScript tergantung strict mode dan validasi saat runtime.
- Developer Node jauh lebih mudah dicari di Indonesia, sedangkan engineer Go biasanya lebih senior dan lebih mahal.
- Kombinasi Node untuk API produk dan Go untuk service berat atau concurrency tinggi itu umum dan berjalan baik.


