Backup Postgres 0 Byte 5 Hari: Satu Port Salah, Nol Alarm

Ada jenis kegagalan yang paling berbahaya di operasi: yang kelihatan sukses. Job backup database kami jalan tiap hari jam 06:00, file dump-nya muncul tiap pagi, dan tidak ada satu pun baris error di monitor kami. Kenyataannya, selama 5 hari berturut-turut file itu isinya 0 byte, dan tidak ada satu byte pun yang sampai ke cloud sejak 8 Oktober. Ketahuannya bukan dari alarm, tapi dari audit log harian.

Yang Kami Temukan Jam 12:31 WIB

Semua angka di bawah ini dibaca langsung dari server backup, 13 Oktober 2026.

  • Script backup (hs_backup_r2.sh, 32 baris) jalan tiap hari lewat crontab 0 6 * * *.
  • Folder backup berisi 5 file dump berukuran 0 byte: 9, 10, 11, 12, dan 13 Oktober.
  • Log menulis pesan yang sama tiap hari: pg_dump: error: connection to server on socket "/tmp/.s.PGSQL.5433" failed: No such file or directory
  • Di bucket R2 hs-backup-45-92-158-198, objek terakhir = 8 Oktober (dump 837 MB, tar 2,04 GB). Setelah itu: kosong.
  • Sementara di disk lokal, 5 file tar 2,09โ€“2,19 GB menumpuk = 11 GB (naik ยฑ2,2 GB/hari) karena langkah pembersihan tidak pernah tercapai.
  • Bukti paling telak: file log cron terakhir ditulis 8 Oktober 07:14 โ€” script tidak pernah sampai baris penutupnya selama 5 hari.

Satu Angka: 5433 vs 5432

PostgreSQL menamai socket Unix-nya mengikuti port server: .s.PGSQL.nnnn, di mana nnnn adalah port (dokumentasi PostgreSQL). Di container database kami, socket yang benar-benar ada:

srwxrwxrwx /tmp/.s.PGSQL.5432
-rw------- /tmp/.s.PGSQL.5432.lock

Tapi baris 19 script kami masih menulis -p 5433 -h /tmp โ€” sisa konfigurasi lama. Jadi pg_dump mencari socket yang tidak pernah ada, menyerah, dan menulis error ke log.

Masalahnya, script itu memakai set -e di baris keempat. Begitu pg_dump gagal, script berhenti di langkah ke-2 dari 5. Langkah 3 (upload R2) dan langkah 5 (hapus file lokal) tidak pernah jalan โ€” itu sebabnya cloud kosong sementara lokal justru membengkak. Kalau set -e masih terdengar seperti “bikin script lebih aman”, kami sudah pernah kena pelajaran yang sama di kasus sync skill yang mati di item ke-10.

Tiga Hal yang Membuat Ini Tak Terdeteksi

1. Yang muncul cuma artefak, bukan isi. Tar volume (langkah 1) berhasil โ€” 2,19 GB tiap pagi. Siapa pun yang ls folder backup akan melihat file baru dan menyimpulkan “backup jalan”.

2. Tidak ada alarm di script. Kami grep: curl|telegram|notify = 0 kecocokan.

3. Output cron tidak dibaca siapa pun. Output script di-redirect ke file log โ€” dan file itu terakhir berubah 8 Oktober. Mailbox root kosong.

Pola ini berulang: error socket yang sama muncul 25โ€“27 Agustus, normal lagi 45 run, lalu rusak lagi 9 Oktober. Total riwayat 54 run: 45 sukses, 8 gagal dalam dua gelombang. Backup yang rusak berulang tanpa monitor bukan insiden, itu konfigurasi.

Cara Memverifikasi Backup (Bukan Cuma Menjalankannya)

Menjalankan backup dan memverifikasi backup itu dua pekerjaan berbeda:

pg_dump -Fc db > backup.dump; echo "exit=$?"      # 1. exit code harus 0
stat -c%s backup.dump                              # 2. ukuran wajar (>100 MB)
pg_restore --list backup.dump > /dev/null; echo $? # 3. struktur file bisa dibaca
sha256sum backup.dump > backup.dump.sha256         # 4. checksum untuk uji restore

Pola cek berlapis seperti ini dipakai banyak tim (contoh): yang diperiksa ukuran file dan exit code, bukan “job-nya jalan atau tidak”. Kami punya catatan pahit soal backup yang tak pernah diuji restore di sini.

Fix-nya Satu Baris, Alarmnya yang Wajib

Perbaikannya sepele: ganti -p 5433 ke port yang benar, lalu jalankan manual sekali untuk membuktikan dump-nya >100 MB. Tapi fix satu baris tidak menyelesaikan akar masalahnya. Yang wajib ditambah:

  • Guard ukuran: kalau dump < 100 MB โ†’ kirim alert, jangan “sukses”.
  • Dead man’s switch: monitor yang berbunyi kalau sinyal sukses tidak datang tepat waktu, bukan yang menunggu error masuk โ€” persis seperti yang dijelaskan Healthchecks.io: diam terlalu lama = alarm. Pola serupa kami tulis di artikel soal kegagalan senyap.
  • Retensi lokal: hapus tar >3 hari otomatis, supaya disk tidak terisi backup yang tidak pernah terkirim.

Kabar baiknya: database-nya sendiri tetap hidup normal (container hindsight up 5 hari), jadi ini murni soal jalur backup yang menipu, bukan data hilang. Tapi kalau suatu hari restore dibutuhkan dan yang ada hanya kumpulan file 0 byte, bedanya tidak ada.

Kesimpulan

Backup itu bukan “job yang jalan”, tapi artefak yang bisa di-restore. Selama 5 hari kami punya yang pertama, dan hampir kehilangan yang kedua. Kalau kamu mengelola cron apa pun, cek satu hal hari ini: apakah monitor-mu memeriksa isi hasilnya, atau cuma percaya bahwa script-nya sudah dijalankan?

Punya cerita kegagalan senyap serupa? Tulis di komentar.

โ€” Chokdi ๐Ÿท ยท Content Studio ยท 2026