Aku Habis Tiga Minggu Mengira Ini Bug Kode, Padahal Cuma Angka Default yang Tidak Pernah Kuubah

Selama tiga minggu, tracker-langganan mati total selama satu sampai dua menit, hampir selalu di antara jam 9 dan 11 pagi WIB, dan hampir selalu di hari kerja. Tidak pernah di akhir pekan, tidak pernah malam hari. Setiap kali kejadian, aku buka dashboard monitoring, semua metrik sudah kembali hijau sebelum aku sempat screenshot apa pun — CPU normal, memori normal, tidak ada deploy yang bertepatan. Insiden yang selesai sendiri sebelum sempat kuselidiki adalah jenis bug paling menyebalkan yang pernah kuhadapi.

Pola yang Baru Kelihatan Setelah Aku Berhenti Mencari di Kode

Reaksi pertamaku selalu sama: buka commit terakhir, cari perubahan mencurigakan di endpoint yang paling sering dipakai pagi hari — endpoint ringkasan tagihan bulanan yang dipanggil dashboard klien begitu mereka login pertama kali di hari itu. Tiga kali berturut-turut aku curiga ke tiga bagian kode yang berbeda, tiga kali pula aku tidak menemukan apa-apa yang berubah di sekitar waktu kejadian.

Baru di minggu kedua aku berhenti mencari perubahan kode dan mulai mencatat waktu kejadian secara manual di spreadsheet: 9:14, 10:02, 9:47, 10:31, 9:05. Begitu dikumpulkan begitu saja, polanya jelas — semua jatuh di jendela dua jam yang sama, jendela yang juga merupakan waktu paling ramai klien-klien tracker-langganan login untuk mengecek tagihan sebelum jam kerja kantor mereka mulai. Bukan soal kode yang berubah. Ini soal beban yang menumpuk di jam tertentu, dan dashboard monitoring-ku ternyata tidak dirancang untuk menangkap beban yang datang lalu hilang dalam hitungan menit.

Kenapa Dashboard Monitoring-ku Buta Terhadap Masalah Ini

Dashboard yang kupasang cuma menyimpan agregat lima menitan — rata-rata CPU, rata-rata latensi, jumlah request per menit. Lonjakan yang durasinya satu-dua menit gampang tenggelam di rata-rata lima menit itu, apalagi kalau lonjakannya bukan soal jumlah request yang mencolok, tapi soal sesuatu yang menyumbat di lapisan yang tidak kupantau sama sekali: koneksi ke database.

Aku baru kepikiran cek itu setelah membuka log Postgres langsung di server, bukan log aplikasi Node.js-ku. Di sana ada baris berulang yang sebelumnya tidak pernah kuperhatikan: FATAL: sorry, too many clients already. Log aplikasi sendiri tidak pernah menampilkan error ini secara jelas — yang muncul di sisi aplikasi cuma request yang timeout setelah menunggu koneksi selama 30 detik, lalu gagal dengan pesan generik yang selama ini kubaca sebagai "server lambat", bukan "server kehabisan slot koneksi".

Seseorang menggunakan MacBook Pro
Seseorang menggunakan MacBook Pro

Angka Default yang Tidak Pernah Kuubah Sejak MVP

Setelah tahu harus mencari apa, penyebabnya cepat ketemu. Pool koneksi database di tracker-langganan diset max: 10 sejak hari pertama aku menulis kodenya — angka yang kuambil begitu saja dari contoh di dokumentasi library pg, waktu itu klienku masih bisa dihitung jari dan sepuluh koneksi lebih dari cukup. Angka itu tidak pernah kusentuh lagi, bahkan setelah jumlah klien bertambah lebih dari sepuluh kali lipat.

Masalahnya bukan cuma jumlah klien yang bertambah, tapi satu endpoint spesifik: ringkasan tagihan bulanan itu menjalankan lima query berurutan per request — satu untuk data langganan, satu untuk riwayat pembayaran, tiga lagi untuk menghitung breakdown pemakaian per fitur, masing-masing memegang satu koneksi dari pool selama query itu berjalan. Kalau delapan-sembilan klien kebetulan membuka dashboard dalam rentang beberapa detik yang sama — persis yang terjadi tiap jam sibuk pagi — endpoint itu sendirian bisa memegang hampir seluruh sepuluh slot pool, dan request lain yang datang bersamaan (termasuk endpoint login) harus antre menunggu koneksi kosong sampai akhirnya timeout.

Yang membuat ini makin sulit dilacak: begitu antrean itu pecah dan koneksi dilepas lagi, semuanya kembali normal dalam hitungan detik, jauh sebelum siapa pun sempat membuka dashboard untuk melihat apa yang barusan terjadi. Bug ini secara harfiah menyembunyikan jejaknya sendiri setiap kali selesai.

Papan sirkuit biru tua dari dekat
Papan sirkuit biru tua dari dekat

Perbaikan yang Kupilih, dan yang Sengaja Tidak Kupilih

Perbaikan paling cepat sebenarnya cuma menaikkan max pool jadi 30. Itu langsung kulakukan hari itu juga karena butuh solusi segera, dan memang langsung menghilangkan gejalanya. Tapi aku tahu itu cuma menunda masalah yang sama sampai jumlah klien naik lagi beberapa kali lipat — menaikkan angka tanpa mengerti kenapa satu endpoint bisa memegang koneksi selama itu cuma memindahkan tembok yang sama beberapa meter ke depan.

Perbaikan kedua, yang kukerjakan minggu berikutnya dengan lebih tenang, adalah menggabungkan lima query di endpoint ringkasan tagihan itu jadi satu query dengan join dan agregasi di sisi database, alih-alih lima permintaan koneksi terpisah yang berjalan satu per satu di kode aplikasi. Waktu eksekusi endpoint itu sendiri turun dari rata-rata 340ms jadi 90ms, dan yang lebih penting, satu request sekarang cuma memegang satu koneksi sesaat, bukan lima koneksi berurutan.

Aku juga menambah satu grafik baru di dashboard monitoring: jumlah koneksi aktif ke database, di-sample tiap 15 detik alih-alih agregat lima menitan. Kalau bug serupa muncul lagi di endpoint lain, aku ingin bisa melihat lonjakannya sebelum sempat hilang sendiri, bukan menebak-nebak dari catatan waktu di spreadsheet.

Takeaway

Bug yang paling sulit dilacak bukan selalu yang paling rumit kodenya — kadang justru angka konfigurasi kecil yang diset sekali di hari pertama dan tidak pernah dipertanyakan lagi setelah skala aplikasi berubah total. Kalau ada gejala yang selalu selesai sendiri sebelum sempat diselidiki, curigai lapisan yang tidak masuk ke dashboard monitoring biasa — di kasusku, itu jumlah koneksi database, bukan CPU atau memori. Dan kalau menaikkan satu angka konfigurasi langsung menghilangkan gejala, itu tanda untuk berhenti sejenak dan cari tahu kenapa, bukan alasan untuk menutup tiket dan lanjut ke pekerjaan berikutnya.

Sumber gambar: Domaintechnik di Unsplash Sumber gambar: Glenn Carstens-Peters di Unsplash Sumber gambar: Vishnu Mohanan di Unsplash

The conversation 0

No comments yet. Start the conversation.

Comments are reviewed before appearing. Links are masked.