Debugging Production Incidents
Debugging di production sangat berbeda dengan development. Kamu tidak bisa sembarangan pause kode atau menambahkan console.log — aplikasi sedang digunakan user sungguhan. Butuh pendekatan sistematis dan hati-hati.
Prinsip Utama
Stabilisasi dulu, investigasi kemudian.
Saat terjadi incident, prioritas pertama adalah mengembalikan layanan — bukan menemukan root cause. Root cause bisa dicari setelah sistem stabil.
Alur Incident Response
1. Deteksi → Alert masuk / laporan user
2. Triase → Seberapa parah? Berapa user terdampak?
3. Koordinasi → Beri tahu tim, assign incident commander
4. Mitigasi → Stabilisasi sistem (rollback jika perlu)
5. Investigasi → Cari root cause
6. Fix → Perbaiki dan deploy
7. Postmortem → Dokumentasikan, cegah terulang
Deteksi Dini
// Monitor error rate dan alert jika melonjak
function analyzeErrorRate(events, windowMs = 60000) {
const now = Date.now();
const recent = events.filter(e => now - e.timestamp <= windowMs);
const errors = recent.filter(e => e.type === "error").length;
const total = recent.length;
const errorRate = total > 0 ? errors / total : 0;
return {
errorRate: Math.round(errorRate * 100), // persen
total,
errors,
};
}
// Deteksi anomali — rate > 2x rata-rata
function detectAnomalies(rates) {
const avg = rates.reduce((s, r) => s + r, 0) / rates.length;
return rates.map((rate, i) => ({
index: i,
rate,
isAnomaly: rate > avg * 2,
}));
}
Teknik Debugging Production
1. Feature Flags
Matikan fitur bermasalah tanpa deploy:
// Semua fitur dilindungi flag
if (featureFlags.isEnabled("new-checkout")) {
return <NewCheckout />;
}
return <OldCheckout />;
2. Canary Deployment
Deploy ke sebagian kecil user dulu:
100% traffic → old version
↓ Deploy canary
5% traffic → new version (monitor)
95% traffic → old version
↓ Jika aman, rollout bertahap
25% → 50% → 100%
3. Log Sampling
Di production, log semuanya bisa membanjiri sistem:
function shouldLog(rate = 0.1) {
return Math.random() < rate; // Log 10% request
}
// Log 100% error, 10% info
if (level === "error" || shouldLog(0.1)) {
logger.log(level, message, context);
}
4. Correlation ID
Lacak satu request di seluruh sistem:
// Frontend: kirim request ID di header
const requestId = crypto.randomUUID();
fetch("/api/orders", {
headers: { "X-Request-ID": requestId }
});
// Backend: log dengan request ID yang sama
logger.info("Order created", { requestId, orderId });
Rollback sebagai Mitigasi
Jika memungkinkan, rollback adalah mitigasi tercepat:
# Vercel
vercel rollback
# Git-based rollback
git revert HEAD --no-edit
git push origin main
# Database: jangan langsung rollback
# Jalankan migration rollback hanya jika aman
php artisan migrate:rollback
Postmortem
Setelah incident selesai, tulis postmortem:
## Incident: Checkout Down (2024-01-15 10:30 - 11:00 WIB)
**Dampak**: 150 user tidak bisa checkout selama 30 menit
**Root Cause**:
Migrasi database menambahkan kolom NOT NULL tanpa default value,
menyebabkan error saat INSERT baru.
**Timeline**:
- 10:30 - Deploy v2.3.1
- 10:32 - Alert error rate naik ke 45%
- 10:35 - Tim mendeteksi, mulai investigasi
- 10:45 - Root cause ditemukan
- 10:55 - Rollback berhasil
- 11:00 - Layanan normal
**Action Items**:
- [ ] Tambahkan default value di semua migration
- [ ] Test migration di staging sebelum production
- [ ] Perbaiki alert agar lebih cepat terdeteksi
Tips Production Debugging
- Jangan panik — ikuti prosedur dengan kepala dingin
- Komunikasikan status — update tim setiap 15-30 menit
- Catat semua langkah — untuk postmortem dan audit
- Test rollback secara berkala — pastikan bisa dilakukan saat dibutuhkan
- Buat runbook — dokumen langkah-langkah untuk skenario umum