Journal archive

ControlInJosh / field note

Firestore yang Sudah Ditinggalkan Tiba-tiba Membaca 15 Juta Data dalam 12 Jam

Firestore yang sudah tidak dipakai lagi tiba-tiba melakukan 15 juta reads dalam 12 jam karena cron job Go gagal menjalankan operasi delete. Kesalahan try-catch membuat proses read berjalan terus-menerus dan menghabiskan hampir Rp350.000.

3 min read0 readers

Firestore yang Sudah Ditinggalkan Tiba-tiba Membaca 15 Juta Data dalam 12 Jam

Hari ini sekitar jam 6 pagi, ada kejadian yang cukup bikin kaget.

Firestore yang sebenarnya sudah aku tinggalkan dari startup aku dan sudah tidak dipakai lagi, tiba-tiba meledak jadi 15 juta reads dalam 12 jam.

Padahal kuota hariannya cuma sekitar 50 ribu reads.

Dalam waktu 12 jam, kita hampir menghabiskan Rp350.000 untuk sesuatu yang sebenarnya sudah tidak dipakai dan sia-sia.

Kejadiannya

Setelah dicek, masalahnya ternyata datang dari cron kita.

Di Go, kita memang bisa membuat cron job worker untuk menjalankan fungsi tertentu secara berkala. Waktu itu worker ini punya fungsi CRUD, salah satunya untuk melakukan delete data di Firestore.

15 M Read. Nice
15 M Read. Nice

Masalahnya, fungsi delete tersebut gagal.

Yang lebih parah, cara kita menangani error-nya juga salah. Aku menyebutnya try catch supaya gampang dibayangkan, walaupun di Go sendiri error biasanya ditangani lewat nilai error yang dikembalikan fungsi, bukan try-catch literal. Pola error handling yang kami pakai membuat proses tidak benar-benar berhenti ketika operasi delete gagal. Bukannya gagal lalu berhenti atau masuk ke mekanisme retry yang aman, operasi read malah terus dijalankan secara brutal dan berulang-ulang.

Akhirnya Firestore terus membaca data, walaupun fungsi utama yang ingin dilakukan sebenarnya adalah delete.

Jadi selama berjam-jam, sistem kita melakukan read tanpa ada yang sadar. Karena database itu sudah tidak dipakai lagi, tidak ada juga yang setiap hari memantau dashboard atau billing-nya.

Sampai akhirnya pagi ini kelihatan bahwa jumlah reads-nya sudah mencapai 15 juta.

Kesalahan yang sebenarnya terjadi

Kalau dilihat sekilas, ini memang kelihatan seperti masalah kecil di cron job. Tapi efeknya bisa langsung menjadi biaya.

Ada beberapa kesalahan yang terjadi bersamaan:

  • Operasi delete gagal, tapi proses worker tidak berhenti dengan benar.
  • Error handling menggunakan pola yang secara praktik seperti try catch, tetapi dengan cara yang salah.
  • Tidak ada batas maksimal retry.
  • Tidak ada backoff ketika proses gagal.
  • Tidak ada monitoring untuk membaca lonjakan penggunaan Firestore.
  • Database yang sudah tidak dipakai tetap dibiarkan aktif tanpa benar-benar dimatikan atau diamankan.

Yang paling mengganggu adalah sebenarnya sistem ini sudah kami tinggalkan. Tapi resource cloud tidak otomatis mengerti bahwa kita sudah tidak peduli lagi pada sistem tersebut.

Kalau masih ada worker, cron, atau service yang hidup, dia tetap akan bekerja. Dan kalau ada bug, dia juga tetap akan membuat tagihan.

Akhirnya turun setelah cron diperbaiki dan direset
Akhirnya turun setelah cron diperbaiki dan direset

Pelajaran yang aku dapat

Pertama, sistem yang sudah tidak dipakai tetap harus dimatikan dengan benar.

Bukan cuma berhenti membuka aplikasinya, lalu menganggap semuanya selesai. Cron job, worker, Cloud Functions, database, scheduled task, dan credential juga perlu dicek satu per satu.

Kedua, error handling itu bukan sekadar membungkus kode dengan try catch.

Kalau error ditangkap tapi setelah itu proses tetap lanjut tanpa kontrol, try catch malah bisa membuat masalah lebih sulit terlihat. Terutama kalau kode tersebut berada di dalam worker atau cron job yang terus berjalan.

Ketiga, setiap retry harus punya batas.

Kalau sebuah operasi gagal, kita perlu tahu kapan harus mencoba lagi, berapa kali boleh mencoba, dan kapan proses harus dianggap gagal total. Retry tanpa batas bisa berubah menjadi loop yang mahal.

Keempat, billing dan usage monitoring tetap penting, bahkan untuk sistem yang sudah tidak dipakai.

Buat sistem yang masih aktif, monitoring itu wajib. Buat sistem yang sudah ditinggalkan, monitoring juga penting untuk memastikan tidak ada sesuatu yang diam-diam masih berjalan.

Hari ini kami membayar hampir Rp350.000 untuk sebuah sistem yang seharusnya sudah mati.

Bukan karena trafik pengguna. Bukan karena ada fitur baru. Bukan karena produk sedang tumbuh.

Hanya karena satu cron job gagal melakukan delete, lalu error handling-nya membuat proses read berjalan terus-menerus.

Kelihatannya sepele. Tapi cloud tidak pernah menganggap hal seperti ini sepele ketika masuk ke billing.

CJControlInJoshControl systems, engineering experiments, and technical ideas made clearer.

Continue the thought

Reader notes (0)

Add a perspective, question, or useful disagreement. Comments are reviewed before appearing here.

0/1500

Loading reader notes…