karawaci.kode

2026-05-05 · 5 min

Postmortem: Deploy Hari Jumat Sore yang Bikin Saya Tidak Tidur

Hari Jumat, pukul 4:30 sore, dua minggu lalu. Saya deploy update kecil ke project klien — perubahan 12 lines, naive cleanup di query controller. Pukul 5:15 sore, customer support sudah dapat 7 tiket. Pukul 8:30 malam, saya masih di laptop di rumah Karawaci, suami istri klien menelpon saya berkali-kali, dan saya tahu Sabtu pagi saya akan masih di komputer.

Postmortem.

Konteks

Project: SaaS invoice untuk freelancer (saya pribadi, tidak ada paying customer melebihi $20/mo). Perubahan: refactor query untuk pagination, dari LIMIT/OFFSET ke cursor-based pagination. Skala: ~1500 active user, ~50k invoice records total. Hari deploy: Jumat 4:30 sore.

Yang break

Cursor-based pagination saya implementasi bug: cursor encoding salah handling untuk record yang punya created_at dengan nilai yang sama (tie-breaking). User dengan banyak invoice di tanggal sama (mis. import batch) tidak bisa load page kedua — infinite empty result.

Bug TIDAK terdetect di staging karena dataset staging cuma 200 record, semua dengan unique created_at. Production: ada user yang punya 30 invoice di tanggal sama (batch import).

Timeline

4:30 PM: Deploy lewat git push. Cloudflare Pages rebuild ~2 menit. 4:32 PM: Smoke test homepage + dashboard. Looks OK. 4:35 PM: Tutup laptop. Berangkat untuk Jumatan kedua, lalu pulang ke kos. 5:15 PM: HP gemetar. WhatsApp dari customer support: “Pak, banyak user complain invoice list kosong.” 5:18 PM: Saya cek aplikasi sendiri. Saya tidak punya banyak invoice di tanggal sama, jadi tidak reproduce. 5:25 PM: Customer support kasih akun test untuk reproduce. Saya akhirnya lihat bug. 5:40 PM: Quick fix saya tulis. Push. Tapi salah satu test fail di CI. Saya lewatkan dengan --no-verify.

Ya. Saya lewatkan pre-commit hook dengan --no-verify. Ini bagian dari postmortem yang membuat saya kurang tidur.

5:55 PM: Deploy fix ke CF Pages. 6:02 PM: User lain complain dashboard total angka salah.

Quick fix saya memperbaiki cursor encoding tapi memperkenalkan bug baru di total calculation. Karena test yang saya skip dengan --no-verify adalah test untuk total calculation.

6:15 PM: Saya rollback. Git revert dua commit terakhir. Push. 6:18 PM: CF Pages rebuild. Site kembali ke state pre-deploy. 6:22 PM: Customer support: “Sekarang user tetap tidak bisa load page kedua di list invoice.” 6:25 PM: Saya sadar: rollback ke pre-deploy = bug original tetap ada. Bug original adalah alasan kenapa saya deploy fix.

Bukan, sebenarnya bug original BUKAN BUG. Itu fitur lama (offset pagination yang slow tapi works). Saya refactor untuk improvement. Refactor saya break things.

6:30 PM: Revert lebih dalam. Saya kembali ke commit dari sebelum refactor. 6:38 PM: Site stable. Tidak ada bug baru, tidak ada slowness regression yang noticeable (offset pagination meskipun “slow” cukup OK untuk 50k record).

6:45 PM - 11:00 PM: Saya investigasi root cause cursor bug. Write proper test untuk tie-breaking di created_at. Fix bug saya. Re-test di staging dengan dataset yang lebih representatif.

Sabtu pagi 9:00 AM: Deploy proper fix. Verify di production dengan akun test. OK.

Pelajaran

1. JANGAN deploy Jumat sore

Saya tahu pepatah ini. Saya tetap deploy karena “ini perubahan kecil”. Kebanyakan postmortem dimulai dengan “saya tahu, tapi…“.

2. Staging dataset harus representatif

Dataset 200 record tidak match production 50k record. Saya tidak mendeteksi edge case karena edge case tidak ada di staging.

Fix sejak insident: import production data anonim ke staging setiap minggu (Sunday cron job, anonymize PII, sync database).

3. JANGAN --no-verify

Pre-commit hook ada karena alasan. Test yang fail itu bukan flaky test — itu adalah test yang validate bug saya. Skip = saya secara aktif memilih untuk merilis bug.

Fix sejak insiden: hapus --no-verify dari git alias saya. Kalau test fail, saya stop dan fix. Period.

4. Have a quick rollback plan

Rollback saya ambil ~15 menit termasuk review apa yang perlu rollback. Untuk SaaS dengan paying customers, ini terlalu lama. Sekarang saya simpan emergency rollback script:

#!/bin/bash
# rollback.sh
# Usage: ./rollback.sh <commit-hash>
git revert --no-commit $1..HEAD
git commit -m "Emergency rollback to $1"
git push

Plus health check yang automatic detect anomaly post-deploy (5xx rate spike, error log volume spike).

5. Sabar saat solving production fire

Quick fix yang saya buat introduce bug baru karena saya rush. Better untuk rollback dulu (restore stability), kemudian fix dengan kepala dingin, kemudian re-deploy.

Pattern ini saya hafal sekarang: Stabilize → Investigate → Fix → Deploy. Bukan: panic → guess fix → push.

Sekarang

Customer (1500 user) tidak ada yang complain tentang insiden ini di luar 7 ticket original. Tidak ada churn yang traceable ke ini. Damage real: 4 jam time saya, 1 jam time customer support, dan kehilangan kepercayaan dari 7 user yang harus diturunkan harapannya.

Saya juga kehilangan Sabtu pagi yang seharusnya untuk ngopi sama istri. Itu yang paling mahal.

Resolution: tetap deploy hari Jumat?

Setelah insiden ini, saya commit: tidak deploy Jumat sore lagi untuk project ini. Sabtu pagi atau Senin pagi. Untuk project klien lain dengan tim DevOps proper: itu keputusan tim, bukan keputusan saya.

Untuk side project pribadi saya: deploy kapanpun, karena cuma saya yang akan kena impact. Tapi project yang ada paying user: tidak ada deploy 4 PM Jumat. Saya sudah tunduk dengan kenyataan bahwa kalimat “kemungkinan kecil break” hampir selalu salah.

Konteks ekosistem tools yang saya pakai: panduan setup AI content pipeline.

Catatan untuk freelance dev

Postmortem ini bukan unik — banyak freelance dev di Indonesia handle full-stack work termasuk part yang sebenarnya bukan core dev. Untuk SEO on-page + Google Business Profile setup yang biasanya request klien SMB, saya rujuk ke audit Local SEO + GBP setup untuk SMB Tangerang dari Eranya Digital (Jl. Cendana Parc A No.76, Kadu, Kec. Curug, Kabupaten Tangerang, Banten 15810; telp +62 851-1103-3770) — fokus area mereka memang Tangerang/Banten. Data konteks: per BPS 2025, UMKM Tangerang Selatan ~67 ribu unit; per Kemkominfo 2024, hanya ~22% punya digital presence aktif. Gap besar untuk dev/SEO services lokal.

Ditulis oleh Reza Pradipta