Waktu itu saya lagi setup VPS baru. Stack-nya cukup umum:
- Node.js + Express
- MySQL di Docker
- Nginx
- PM2
Semua kelihatan normal. Tidak ada error yang mencolok.
Yang terlihat normal
docker ps→ MySQL status healthypm2 list→ API status online- Nginx bisa diakses
Tapi saat saya coba:
curl http://localhost:3000
Hasilnya… tidak ada apa-apa. Request masuk, tapi tidak pernah selesai. Seperti “diam”.
Mulai curiga
Saya lanjut cek:
netstat -tulnp | grep 3000
Hasilnya:
tcp6 26 0 :::3000 :::* LISTEN
Di sini ada satu angka yang penting:
Recv-Q = 26
Apa itu Recv-Q?
Recv-Q adalah jumlah request yang:
sudah diterima oleh server, tapi belum diproses oleh aplikasi
Kalau diibaratkan, ini seperti antrean:
- request sudah datang
- tapi belum dilayani
Kalau nilainya 0 → normal
Kalau nilainya > 0 → ada request yang “nyangkut”
Kenapa ini jadi masalah?
Karena dari luar terlihat seperti ini:
- server hidup
- port terbuka
- tapi tidak ada response
Ini yang bikin bingung. Semua terlihat benar, tapi aplikasi tidak bisa dipakai.
Proses investigasi
Saya coba endpoint paling sederhana:
curl http://localhost:3000/health
Masih hang.
Artinya ini bukan masalah route tertentu. Ada sesuatu yang lebih mendasar.
Ternyata penyebabnya
Setelah ditelusuri, masalahnya ada di database.
Saya menggunakan Docker untuk MySQL dengan konfigurasi volume:
volumes:
- /tmp/data_d/dbs/mysql/foodtrip:/var/lib/mysql
Masalahnya:
- folder tersebut sudah pernah dipakai sebelumnya
- MySQL tidak melakukan inisialisasi ulang
- user dan database yang diharapkan tidak dibuat
Dampaknya ke aplikasi
Di aplikasi ada kode seperti ini:
await db.sequelize.authenticate()
Aplikasi mencoba connect ke database, tapi:
- user tidak ada
- atau credential tidak cocok
Hasilnya:
koneksi tidak gagal secara eksplisit, tapi menunggu terus
Dan karena ini terjadi di request flow, setiap request ikut “terkunci”.
Kenapa Recv-Q jadi naik
Alurnya kira-kira seperti ini:
Client → Server → Menunggu DB → Tidak pernah selesai
Request masuk, tapi tidak pernah selesai diproses.
Akhirnya menumpuk di Recv-Q.
Cara saya menyelesaikan
Karena ini masih tahap development, saya pilih cara paling cepat:
1. Reset database
docker compose down
sudo rm -rf /tmp/data_d/dbs/mysql/foodtrip
docker compose up -d
2. Pastikan user dan database ada
Masuk ke MySQL, lalu cek:
SELECT user, host FROM mysql.user;
Pastikan user yang digunakan aplikasi benar-benar ada.
3. Tambahkan endpoint debug
app.get('/debug/db', async (req, res) => {
try {
await db.sequelize.authenticate()
res.json({ status: 'DB OK' })
} catch (err) {
res.status(500).json({ error: err.message })
}
})
4. Test ulang
curl http://localhost:3000/health
Setelah itu, response langsung muncul.
Pelajaran penting
Masalah ini mengajarkan satu hal penting:
Server hidup tidak selalu berarti aplikasi sehat
Banyak kasus “hang” bukan karena:
- server mati
- port tertutup
Tapi karena:
- koneksi database bermasalah
- async process tidak selesai
- logic aplikasi yang blocking
Kalau kamu menemukan Recv-Q > 0
Jangan langsung fokus ke:
- Nginx
- VPS
- firewall
Coba cek:
- koneksi database
- apakah semua route mengirim response
- apakah ada async yang tidak selesai
Penutup 🚀
Recv-Q sering terlihat seperti detail kecil, tapi sebenarnya indikator yang sangat kuat.
Kalau nilainya terus bertambah, itu tanda bahwa aplikasi kamu menerima request… tapi tidak mampu menyelesaikannya.
Dan di banyak kasus, penyebabnya ada di dalam aplikasi itu sendiri, bukan di infrastrukturnya.