Production incident adalah gangguan di aplikasi yang sedang dipakai user sungguhan: checkout gagal, halaman error, atau API lambat. Debugging-nya beda dengan di laptop, karena tiap menit yang lewat ada user yang kena. Bayangin pipa bocor di rumah. Yang pertama kamu lakukan adalah menutup keran utama supaya airnya berhenti, baru mencari sambungan mana yang bocor, lalu mencatat penyebabnya supaya gak terulang. Di production urutannya sama: hentikan dampaknya dulu, cari penyebabnya kemudian.
🧪 Tebakan cepat: jam 10.30 kamu deploy v2.3.1. Semenit kemudian error rate naik dari 5% jadi 50%. Langkah pertama: cari baris kode yang salah, atau kembalikan dulu ke versi sebelumnya? Jawabannya ada di bagian "Langkah saat incident".
Kenapa production beda
- Gak boleh pasang breakpoint. Debugger yang berhenti di breakpoint membekukan proses. Di Node.js, semua request dilayani satu thread yang sama, jadi begitu proses berhenti, semua request user ikut menggantung.
- Susah direproduksi. Datanya data asli, user-nya ribuan, dan bug-nya sering cuma muncul di kombinasi tertentu yang gak ada di staging.
- Alatnya beda. Yang kamu andalkan adalah log, error monitoring (pelajaran sebelumnya), metrik seperti error rate, dan tracing.
Langkah saat incident
- Deteksi: alert berbunyi atau user melapor.
- Triase: seberapa parah, fitur apa, berapa user yang kena.
- Mitigasi: hentikan dampaknya. Rollback, matikan feature flag, atau tarik canary.
- Investigasi: cari root cause (penyebab aslinya) lewat log, trace, dan error monitoring.
- Fix: perbaiki, tes di staging, deploy.
- Postmortem: tulis apa yang terjadi dan apa yang diubah supaya gak terulang.
Mitigasi datang sebelum investigasi. Kalau deploy barusan bikin error rate 50%, kembalikan dulu versi sebelumnya atau matikan fiturnya, baru cari baris yang salah dengan tenang. Itu jawaban tebakannya.
Deteksi: error rate dan anomali
Error rate adalah persentase request yang gagal dalam sebuah jendela waktu (window), misalnya 60 detik terakhir. Jendelanya diukur mundur dari event terbaru, bukan dari jam sekarang, supaya data yang sudah lewat tetap bisa dianalisis. Ini lima event dari latihan (waktu dalam milidetik, now = waktu sekarang):
| Event | type | timestamp | Masuk window 60.000 ms? |
|---|---|---|---|
| 1 | success | now - 5000 | ya |
| 2 | success | now - 4000 | ya |
| 3 | error | now - 3000 | ya |
| 4 | error | now - 2000 | ya |
| 5 | success | now - 1000 | ya, ini yang terbaru |
Total 5, error 2, jadi error rate 2 / 5 = 40%.
Lalu, menit mana yang janggal? Anomali di sini artinya error rate di atas dua kali rata-ratanya. Error rate per menit [5, 4, 6, 50, 5] rata-ratanya 70 / 5 = 14, jadi batasnya 28. Cuma 50 yang lewat, yaitu menit ke-4 (index 3).
function analyzeErrorRate(events, windowMs = 60000) {
if (events.length === 0) return { errorRate: 0, total: 0, errors: 0 };
const terbaru = Math.max(...events.map((e) => e.timestamp));
const dalamWindow = events.filter((e) => terbaru - e.timestamp <= windowMs);
const errors = dalamWindow.filter((e) => e.type === 'error').length;
return {
errorRate: Math.round((errors / dalamWindow.length) * 100), // persen, bulat
total: dalamWindow.length,
errors: errors,
};
}
function detectAnomalies(rates) {
const rata = rates.reduce((a, b) => a + b, 0) / rates.length;
return rates.map((rate, index) => ({ index, rate, isAnomaly: rate > 2 * rata }));
}
const now = Date.now();
const events = [
{ type: 'success', timestamp: now - 5000 },
{ type: 'success', timestamp: now - 4000 },
{ type: 'error', timestamp: now - 3000 },
{ type: 'error', timestamp: now - 2000 },
{ type: 'success', timestamp: now - 1000 },
];
const analysis = analyzeErrorRate(events, 60000);
console.log(analysis.total); // 5
console.log(analysis.errors); // 2
console.log(analysis.errorRate); // 40
const anomalies = detectAnomalies([5, 4, 6, 50, 5]);
console.log(anomalies.filter((a) => a.isAnomaly).length); // 1
console.log(anomalies[3].isAnomaly); // true
Math.max(...events.map(...))mencari timestamp terbaru. Jendelanya dihitung mundur dari situ.terbaru - e.timestamp <= windowMsmembuang event yang lebih tua dari jendela. Dengan event di 1.000, 2.000, dan 90.000 ms dan window 5.000 ms, cuma event 90.000 yang masuk: total 1.Math.round(... * 100)mengubah 0,4 jadi 40, bilangan bulat.rate > 2 * ratapakai>, jadi rate yang tepat dua kali rata-rata belum dianggap anomali. Untuk[1, 1, 10], rata-ratanya 4, dan cuma index 2 yang lewat 8.
Mitigasi: rollback, feature flag, canary
- Rollback: deploy lagi versi sebelumnya. Paling cepat kalau penyebabnya jelas deploy terakhir, tapi semua isi rilis itu ikut ditarik.
- Feature flag: fitur baru dibungkus saklar yang bisa dimatikan dari dashboard, tanpa deploy. Contohnya
if (flags.isEnabled('new-checkout')) { ... }: begitu flag-nya dimatikan, semua user kembali ke checkout lama. - Canary deployment: versi baru dikirim ke sebagian kecil user dulu, misalnya 5%. Kalau v2.3.1 bikin 45 dari tiap 100 request gagal, di canary 5% cuma 5 request per menit yang sampai ke v2.3.1, dan 2 di antaranya gagal. Error rate total naik dari 5% ke 7% saja, sementara grup canary-nya sendiri 40%. Kamu cukup menarik 5% itu, atau mematikan flag-nya, tanpa deploy ulang. Makanya error rate grup canary dipantau terpisah.
Investigasi tanpa mengganggu user
- Logging yang lebih detail di bagian yang dicurigai, dengan request ID (correlation ID): frontend mengirim header
X-Request-ID, dan tiap service menulis ID yang sama di log-nya. Satu pencarian menemukan perjalanan satu request. - Distributed tracing (OpenTelemetry, Jaeger, Zipkin) mencatat satu request dari frontend ke API ke database, lengkap dengan lama tiap langkah. Bug yang cuma muncul di production biasanya ketemu lewat log dan trace ini.
- Hindari menaikkan semua log ke level debug sekaligus: volumenya membanjiri sistem, mahal, dan bisa ikut mencatat data pribadi.
📌 Postmortem
Setelah layanan normal, tulis postmortem singkat: dampaknya (misalnya 150 user gagal checkout selama 30 menit), timeline per menit, root cause, dan action item (tes migrasi di staging, alert lebih cepat). Fokusnya pada sistem dan proses, bukan mencari siapa yang salah.
⚠️ Jebakan yang sering ketemu
- Investigasi dulu, mitigasi belakangan. Selama kamu membaca kode, user terus gagal bayar. Stabilkan dulu.
- Jendela dari
Date.now(). Di latihan, jendelanya diukur dari timestamp terbaru di data. Kalau dari jam sekarang, data lama terbuang semua. - Lupa dikali 100 atau dibulatkan.
errorRateharus40, bukan0.4atau40.0001. - Rata-rata ikut naik. Kalau incident-nya berlangsung lama, misalnya
[5, 4, 6, 50, 50, 50], rata-ratanya 27,5 dan gak ada yang lewat 55. Bandingkan juga dengan rata-rata sebelum incident.
TL;DR: Saat incident: deteksi, triase, mitigasi (rollback, matikan feature flag, tarik canary), baru investigasi, fix, dan postmortem. Jangan pasang debugger di production: breakpoint membekukan proses dan semua request user. Error rate = error dibagi total dalam jendela yang diukur mundur dari event terbaru, dikali 100 dan dibulatkan (5 event, 2 error, jadi 40). Anomali = rate di atas dua kali rata-rata ([5, 4, 6, 50, 5]: rata-rata 14, cuma 50 yang lewat 28). Bug yang cuma muncul di production diselidiki dengan logging detail, request ID, dan distributed tracing, dan canary bikin bug baru cuma kena sebagian kecil user.