Autoscaling melindungi TokoKita dari lonjakan beban, tetapi tidak dari kehilangan region: gangguan besar di pusat data penyedia cloud, kesalahan konfigurasi yang menghapus bucket, hingga ransomware yang mengenkripsi seluruh cluster. Backup dan disaster recovery (DR) adalah dua pertahanan untuk skenario tersebut, dan keduanya harus diukur dengan angka sebelum dibangun. Chapter ini menetapkan metrik RPO/RTO, membandingkan strategi backup dengan simulasi nyata, lalu menyusun rencana DR di level infrastruktur cloud — melengkapi mekanika backup di level database yang sudah dibahas pada Chapter Backup dan Recovery.
RPO dan RTO: Dua Angka yang Menentukan Semuanya #
RPO (Recovery Point Objective) adalah batas usia data yang boleh hilang: RPO 24 jam berarti kegagalan boleh membuang maksimal transaksi satu hari terakhir. RTO (Recovery Time Objective) adalah batas lama layanan boleh berhenti sebelum pemulihan selesai. Kedua angka ini ditetapkan dari kebutuhan bisnis, bukan dari kemampuan teknologi.
Diagram di atas memperlihatkan hubungan keduanya: RPO diukur mundur dari momen kegagalan ke titik pemulihan terakhir, sedangkan RTO diukur maju dari momen kegagalan sampai layanan kembali hidup. Semakin kecil keduanya, semakin mahal strategi yang dibutuhkan.
Angka TokoKita ditetapkan dari dampak bisnis, bukan dari selera teknis. Data pesanan checkout tidak boleh hilang lebih dari beberapa menit (RPO kecil) dan layanan harus kembali dalam satu jam (RTO kecil). Sebaliknya, tabel agregat harian untuk dashboard bisa dibangun ulang dari zona raw, sehingga RPO 24 jam dan RTO satu hari masih dapat diterima. Membedakan kelas data seperti ini mencegah kita membayar perlindungan berat untuk data yang murah dibangun ulang.
Strategi Backup: Full, Incremental, Differential #
Mekanika pg_dump dan backup online sudah kita kuasai di Chapter Backup dan Recovery. Di level infrastruktur, pertanyaannya berbeda: bagaimana kombinasi strategi memengaruhi ukuran penyimpanan dan rantai restore? Simulasi berikut menghitung satu siklus 7 hari untuk data warehouse TokoKita sebesar 500 GB dengan perubahan 25 GB per hari.
"""Simulasi strategi backup 7 hari: full + incremental vs full + differential.
Menghitung ukuran backup per hari, total penyimpanan siklus, rantai restore
(jumlah berkas + byte yang dibaca), dan waktu restore dengan asumsi
throughput. Semua angka dasar adalah asumsi eksplisit.
"""
FULL_GB = 500 # ukuran full backup
UBAH_HARIAN_GB = 25 # data berubah per hari (5% dari 500 GB)
THROUGHPUT_GB_JAM = 200 # kecepatan restore dari object storage
HARI = 7 # siklus: full hari 0, harian hari 1-6
print(f"Asumsi: full {FULL_GB} GB, perubahan harian {UBAH_HARIAN_GB} GB, "
f"restore {THROUGHPUT_GB_JAM} GB/jam\n")
# strategi A: full + incremental harian (perubahan sejak backup TERAKHIR apa pun)
# strategi B: full + differential harian (perubahan sejak FULL TERAKHIR)
ukuran_a = [FULL_GB] + [UBAH_HARIAN_GB] * (HARI - 1)
ukuran_b = [FULL_GB] + [UBAH_HARIAN_GB * d for d in range(1, HARI)]
print("| Hari | A: tipe (GB) | B: tipe (GB) | Rantai restore A | Rantai restore B |")
print("|---|---|---|---|---|")
for d in range(HARI):
label_a = "full" if d == 0 else "incr"
label_b = "full" if d == 0 else "diff"
berkas_a = d + 1 # full + d incremental
byte_a = FULL_GB + UBAH_HARIAN_GB * d
berkas_b = 1 if d == 0 else 2 # full + differential terakhir
byte_b = FULL_GB if d == 0 else FULL_GB + UBAH_HARIAN_GB * d
print(f"| {d} | {label_a} ({ukuran_a[d]}) | {label_b} ({ukuran_b[d]}) "
f"| {berkas_a} berkas, {byte_a} GB | {berkas_b} berkas, {byte_b} GB |")
total_a = sum(ukuran_a)
total_b = sum(ukuran_b)
print()
print(f"Total disimpan per siklus : A {total_a} GB vs B {total_b} GB "
f"(B +{total_b - total_a} GB, {total_b/total_a:.2f}x)")
# restore terburuk: hari 6 (sehari sebelum full berikutnya)
berkas_a, byte_a = 7, FULL_GB + UBAH_HARIAN_GB * 6
berkas_b, byte_b = 2, FULL_GB + UBAH_HARIAN_GB * 6
print(f"Restore terburuk (hari 6) : A {berkas_a} berkas / {byte_a} GB, "
f"B {berkas_b} berkas / {byte_b} GB")
print(f"Waktu restore (worst case) : A {byte_a / THROUGHPUT_GB_JAM:.2f} jam, "
f"B {byte_b / THROUGHPUT_GB_JAM:.2f} jam "
f"(@{THROUGHPUT_GB_JAM} GB/jam, byte sama)")
# RPO skenario: backup harian jam 02:00 vs arsip log transaksional berkelanjutan
print()
print("RPO (usia data maksimum saat terjadi kegagalan):")
print("| Skema backup | RPO terburuk | Konsekuensi |")
print("|---|---|---|")
print("| Full mingguan saja | 7 hari | kehilangan transaksi 1 minggu penuh |")
print("| Harian jam 02:00 | ~24 jam | pesanan seharian hilang bila gagal jam 01:59 |")
print("| Harian + arsip log berkelanjutan | menit | restore ke titik terakhir |")Output yang Dihasilkan:
Asumsi: full 500 GB, perubahan harian 25 GB, restore 200 GB/jam
| Hari | A: tipe (GB) | B: tipe (GB) | Rantai restore A | Rantai restore B |
|---|---|---|---|---|
| 0 | full (500) | full (500) | 1 berkas, 500 GB | 1 berkas, 500 GB |
| 1 | incr (25) | diff (25) | 2 berkas, 525 GB | 2 berkas, 525 GB |
| 2 | incr (25) | diff (50) | 3 berkas, 550 GB | 2 berkas, 550 GB |
| 3 | incr (25) | diff (75) | 4 berkas, 575 GB | 2 berkas, 575 GB |
| 4 | incr (25) | diff (100) | 5 berkas, 600 GB | 2 berkas, 600 GB |
| 5 | incr (25) | diff (125) | 6 berkas, 625 GB | 2 berkas, 625 GB |
| 6 | incr (25) | diff (150) | 7 berkas, 650 GB | 2 berkas, 650 GB |
Total disimpan per siklus : A 650 GB vs B 1025 GB (B +375 GB, 1.58x)
Restore terburuk (hari 6) : A 7 berkas / 650 GB, B 2 berkas / 650 GB
Waktu restore (worst case) : A 3.25 jam, B 3.25 jam (@200 GB/jam, byte sama)
RPO (usia data maksimum saat terjadi kegagalan):
| Skema backup | RPO terburuk | Konsekuensi |
|---|---|---|
| Full mingguan saja | 7 hari | kehilangan transaksi 1 minggu penuh |
| Harian jam 02:00 | ~24 jam | pesanan seharian hilang bila gagal jam 01:59 |
| Harian + arsip log berkelanjutan | menit | restore ke titik terakhir |Mari kita telaah baris-baris kode di atas:
- Baris 14-15 (dua strategi): incremental menyimpan perubahan sejak backup terakhir apa pun, sehingga ukurannya konstan 25 GB. Differential menyimpan perubahan sejak full terakhir, sehingga membesar setiap hari.
- Baris 24-30 (rantai restore): untuk memulihkan hari ke-6, strategi A harus membaca full plus enam incremental (7 berkas), sedangkan strategi B cukup full plus differential terakhir (2 berkas). Total byte sama — 650 GB — tetapi rantai yang pendek mengurangi langkah dan titik kegagalan.
- Baris 44-48 (waktu restore): karena byte yang dibaca sama, waktu restore pun sama. Pilihan strategi ditentukan oleh trade-off penyimpanan (B 1,58 kali lebih besar) versus kesederhanaan rantai restore (B lebih pendek) — bukan oleh kecepatan.
Aturan 3-2-1 dan Replikasi Lintas Region #
Praktik yang telah lama diuji industri merumuskan aturan 3-2-1: simpan 3 salinan data, di 2 jenis media berbeda, dengan 1 salinan di lokasi geografis terpisah. Di cloud, bentuknya konkrit: data utama di database, backup otomatis di penyimpanan terkelola, dan salinan lintas region di region kedua. Replikasi lintas region menyalin objek atau snapshot ke region cadangan secara otomatis — region penyimpanan yang tersedia di tiap penyedia dijelaskan di AWS Backup dan Cloud Storage locations .
Perlu dibedakan dari replikasi database yang dibahas di Chapter Replikasi Database: replikasi menjaga salinan hampir-waktu-nyata untuk ketersediaan dan skala baca, sedangkan backup menjaga titik waktu untuk pemulihan. Keduanya saling melengkapi, bukan menggantikan. Perhatikan juga bahwa replikasi lintas region menyalin data secara berkelanjutan sehingga menimbulkan biaya transfer keluar region (egress) yang harus masuk perhitungan anggaran — jebakan biaya ini dibahas tuntas di chapter penutup section.
DR Drill: Membuktikan Rencana Bekerja #
Rencana DR yang tersimpan di dokumen belum terbukti apa pun. DR drill adalah latihan memulihkan layanan di region cadangan secara berkala. Checklist minimal TokoKita:
- Tetapkan urutan pemulihan layanan: database transaksi lebih dulu, baru pipeline ETL, terakhir dashboard.
- Nyatakan RPO/RTO tiap layanan di runbook, beserta pemiliknya.
- Uji restore penuh dari salinan lintas region setiap kuartal, catat durasi aktual, dan bandingkan dengan RTO.
- Simpan konfigurasi infrastructure as code di repositori terpisah dari data — region bisa hilang, repositori Git harus tetap hidup.
- Latih tim dengan skenario “region utama tidak tersedia selama 24 jam”, bukan sekadar “restore satu tabel”.