Episode ini membuktikan backup kalian benar-benar bisa dipulihkan: melakukan restore test berkala ke instance terpisah, memvalidasi data dengan checksum dan row count, mengotomatiskan drill dengan skrip + report, serta mendokumentasikan runbook recovery. Backup yang tidak pernah diuji bukanlah backup.

Di episode 9 kita melatih recovery manual — sekarang kita naik level: menjadikan pengujian restore sebagai rutinitas terjadwal. Ini perbedaan antara tim yang "punya backup" dan tim yang "tahu backup-nya bekerja". Banyak organisasi baru menyadari backup mereka rusak justru saat membutuhkannya — dan saat itulah segalanya sudah terlambat.
Filosofi episode ini sederhana dan tanpa kompromi: backup yang tidak pernah di-restore bukanlah backup. Ia adalah harapan yang disamarkan sebagai rencana.
Backup bisa sukses selama bertahun-tahun — log bersih, info tampak sehat — tetapi restore tetap gagal. Penyebabnya beragam: file backup terkorupsi diam-diam, WAL yang terlewat, kompresi yang rusak, atau konfigurasi yang berubah setelah backup dibuat. Hanya membongkar dan menjalankan yang membuktikan semuanya utuh.
Setiap drill adalah bukti: backup yang diambil hari ini, benar-benar bisa menghidupkan database besok. Ini bukan latihan yang menyenangkan — ini audit kejujuran terhadap sistem yang kalian bangun di 15 episode sebelumnya.
Drill dilakukan ke instance terpisah — direktori PGDATA yang berbeda, port berbeda, dan bukan host yang sama dengan production. Tujuannya menguji backup, bukan merusak environment yang sehat.
sudo mkdir -p /var/lib/postgresql/drill
sudo chown postgres:postgres /var/lib/postgresql/drill
sudo -u postgres pgbackrest --stanza=main --delta \
--pg1-path=/var/lib/postgresql/drill restoreSesuaikan port di postgresql.conf hasil restore agar tidak bentrok dengan production:
sudo -u postgres sed -i "s/^port = .*/port = 5433/" /var/lib/postgresql/drill/postgresql.confLalu start instance drill:
sudo -u postgres /usr/lib/postgresql/16/bin/pg_ctl -D /var/lib/postgresql/drill -l /tmp/drill.log startNote
Saat drill PITR (bukan restore polos), tambahkan --target-action=pause lalu verifikasi data sebelum resume — persis prosedur episode 8. Dengan cara ini drill juga menguji logika PITR, bukan hanya kemampuan menyalin file.
Restore yang "berhasil start" belum cukup. Validasi data dengan tiga lapis:
SELECT count(*) FROM aplikasi.pelanggan;
SELECT count(*) FROM aplikasi.pesanan;Bandingkan dengan angka yang dicatat saat produksi (bisa dari query harian atau dari backup sebelumnya).
Jalankan validasi blok di level PostgreSQL:
SET default_table_access_method = heap;
SELECT sum(hashtextextended(row_to_json(t)::text, 0))
FROM aplikasi.pelanggan t;Atau gunakan pg_checksums untuk memvalidasi integritas file data:
sudo -u postgres /usr/lib/postgresql/16/bin/pg_checksums -c -D /var/lib/postgresql/drillJalankan beberapa query yang merepresentasikan workload nyata — transaksi terbaru, laporan harian, pencarian. Jika hasilnya masuk akal, data pulih dengan benar.
Warning
Validasi row count saja bisa menipu: jumlah row sama, tetapi isi bisa berbeda (misalnya restore ke waktu yang salah). Kombinasikan row count, checksum, dan query bisnis agar drill membuktikan apa yang pulih, bukan hanya berapa banyak.
Drill bulanan harus bisa dijalankan satu perintah dan menghasilkan laporan. Skrip inti:
#!/usr/bin/env bash
set -euo pipefail
stanza="main"
drill_dir="/var/lib/postgresql/drill"
report="/var/log/pgbackrest/drill-report.txt"
rm -rf "$drill_dir"
mkdir -p "$drill_dir"
chown postgres:postgres "$drill_dir"
sudo -u postgres pgbackrest --stanza="$stanza" --delta \
--pg1-path="$drill_dir" restore
sudo -u postgres /usr/lib/postgresql/16/bin/pg_ctl \
-D "$drill_dir" -l /tmp/drill.log start
result=$(sudo -u postgres psql -p 5433 -d aplikasi -tAc \
"SELECT 'row_count=' || count(*) FROM pelanggan;")
echo "=== PGBACKREST DRILL REPORT ===" > "$report"
echo "tanggal: $(date -Is)" >> "$report"
echo "stanza: $stanza" >> "$report"
echo "hasil: $result" >> "$report"
echo "=== SELESAI ===" >> "$report"
sudo -u postgres /usr/lib/postgresql/16/bin/pg_ctl -D "$drill_dir" stop -m fastJadwalkan bulanan via systemd timer, dan buat alert (episode 14) yang terpicu jika script gagal atau report tidak mengandung row_count=.
Simpan report dalam direktori yang di-archive (misal S3, episode 12). Report ini menjadi bukti audit bahwa recovery memang diuji — penting untuk tim yang tunduk pada kepatuhan (SLA, ISO, HIPAA, dsb.).
Runbook adalah dokumen yang menyelamatkan malam saat on-call. Struktur yang wajib ada:
## Skenario: Kehilangan PGDATA
1. Stop service: systemctl stop postgresql
2. Hapus PGDATA: rm -rf /var/lib/postgresql/16/main
3. Restore: sudo -u postgres pgbackrest --stanza=main --type=immediate restore
4. Start: systemctl start postgresql
5. Verifikasi: psql -c "SELECT count(*) FROM aplikasi.pelanggan;" (harus = 10420)
6. Jika tidak cocok: hubungi DBA senior sebelum melanjutkanTip
Uji runbook-nya juga: minta anggota tim lain mengikuti runbook tanpa bantuan kalian. Jika mereka bingung atau ragu, runbook belum cukup baik. Runbook yang baik adalah yang bisa dijalankan oleh orang yang baru pertama kali melihatnya.
Inti yang harus dibawa pulang:
Di episode 17 selanjutnya kita akan mengikuti perkembangan versi: v2.59.0 & fitur terbaru — rilis 20 Juli 2026 dengan dukungan PostgreSQL 17/18, perbaikan-perbaikan pentingnya, serta jejak rilis 2.56 (perbaikan S3) dan 2.54 (backup dari standby). Menjaga pgBackRest tetap ter-update adalah bagian dari menjaga backup kalian tetap andal!