โ† Semua pembelajaran / Astro Nol โ†’ Portal Berita
Fase 9 ยท Migrasi dari CodeIgniter 3

Runbook cutover & rollback

Runbook yang ditulis saat tenang adalah satu-satunya yang berguna saat tidak tenang. Ini kerangkanya, lengkap dengan hal yang paling sering terlupa.

Intisari

  • Tetapkan ambang batal yang numerik sebelum mulai โ€” bukan "kalau kelihatan buruk".
  • Tunjuk satu orang yang berwenang memutuskan rollback. Bukan rapat.
  • Rollback harus bisa dilakukan dalam di bawah 60 detik dan sudah pernah dilatih.
  • Jangan cutover pada hari Jumat, saat libur, atau saat ada peristiwa berita besar.
  • Yang paling sering terlupa: memberi tahu redaksi, dan menonaktifkan cron di sistem lama.

Sebelum hari-H

WaktuPekerjaanSelesai kalau
H-14Uji paritas seluruh sampelSemua gerbang hijau
H-14Uji beban ke angka trafik puncak (Fase 11)p95 di bawah target
H-7Verifikasi seluruh peta redirectNol 404 di daftar
H-7Latih rollback di lingkungan ujiTerukur < 60 detik
H-3Beri tahu redaksi & dukungan pelangganSudah dikonfirmasi terbaca
H-1Bekukan perubahan di kedua sistemTidak ada deploy lain
H-1Cadangan database, verifikasi bisa dipulihkanUji pemulihan berhasil
H-1Turunkan TTL DNS kalau ada perubahan DNSโ€”

"Verifikasi cadangan bisa dipulihkan" berarti benar-benar memulihkannya ke instance lain. Cadangan yang tidak pernah diuji bukan cadangan โ€” ia harapan. Ini satu-satunya jaring pengaman untuk kesalahan yang tidak bisa di-rollback dengan mengubah aturan Cloudflare.

Kapan tidak melakukan cutover

JanganKenapa
Jumat soreMasalah ditemukan Sabtu, tim tidak lengkap
Menjelang libur panjangSama, lebih parah
Saat ada peristiwa berita besarTrafik puncak, taruhannya paling tinggi
Akhir bulan / awal bulanSiklus penagihan langganan
Saat orang kunci sedang cutiโ€”

Waktu terbaik untuk portal berita Indonesia biasanya Selasa atau Rabu pagi โ€” trafik sedang, tim lengkap, dan masih ada tiga hari kerja untuk menangani apa pun yang muncul.

Hari-H

T-30m  Umumkan di kanal tim. Semua orang siap.
T-15m  Naikkan jumlah task ECS ke 2ร— normal (cache dingin).
T-10m  Verifikasi kesehatan Astro: /sehat, /siap, koneksi database.
T-5m   Verifikasi rollback siap: Origin Rule tinggal dinonaktifkan.

T-0    Aktifkan Origin Rule untuk 5% trafik.
T+5m   Periksa: 5xx, p95, cf-cache-status, log error.
T+15m  Kalau bersih โ†’ 25%.
T+30m  Kalau bersih โ†’ 50%.
T+60m  Kalau bersih โ†’ 100%.

T+2j   Turunkan task ECS ke normal setelah cache hangat.
T+4j   Kirim sitemap baru di Search Console.
T+24j  Tinjau seluruh metrik; putuskan lanjut atau mundur.

Ambang batal โ€” tetapkan sekarang, bukan nanti

MetrikBatalkan kalauSumber
Tingkat 5xx> 0,5% selama 5 menitCloudflare Analytics
p95 latensi origin> 2ร— baseline CI3ALB / CloudWatch
Error webhook pembayaranBerapa punLog aplikasi
Kebocoran isi premiumSatu sajaUji asap otomatis
Kegagalan login> 2ร— baselineLog aplikasi
Koneksi database> 80% max_connectionsCloudWatch
Laporan dari redaksiTidak bisa menerbitkanKanal tim

Angka-angka ini disepakati sebelum cutover dan tidak dinegosiasikan saat berlangsung. Di tengah peluncuran, semua orang punya insentif untuk menafsirkan angka secara optimis โ€” sudah banyak pekerjaan yang dikeluarkan, dan mundur terasa seperti kegagalan. Ambang yang ditulis lebih dulu menghapus perdebatan itu.

Prosedur rollback

1. Nonaktifkan Origin Rule di dashboard Cloudflare.       (~10 detik)
2. Verifikasi: curl -sI https://portal.contoh.id/berita/uji | grep x-dilayani
   โ†’ harus "ci3"                                           (~10 detik)
3. Umumkan di kanal tim: "rollback selesai, dilayani CI3".
4. Biarkan ECS tetap berjalan โ€” jangan matikan apa pun.
5. Kumpulkan bukti SEBELUM memperbaiki: log, metrik, tangkapan layar.
6. Baru cari akar penyebabnya.

Langkah 5 paling sering dilewati dan paling disesali. Setelah rollback, godaan untuk langsung memperbaiki sangat besar โ€” dan log yang berputar akan menghapus bukti dalam hitungan jam. Ambil salinannya dulu; sepuluh menit di sini menghemat dua hari menebak-nebak.

Yang tidak bisa di-rollback dengan aturan Cloudflare

HalKenapaPencegahan
Migrasi skema yang menghapus kolomCI3 tidak bisa jalan lagiTunda sampai CI3 mati
Data yang ditulis Astro dengan format baruCI3 tidak memahaminyaKompatibel dua arah (Fase 2)
Sesi yang dibuat dengan skema baruMember ter-logout saat rollbackTabel sesi bersama (Fase 5)
Webhook yang sudah diproses AstroIdempotensi menyelamatkanmuFase 6
Email yang sudah terkirimTidak bisa ditarikBatasi laju di jam pertama

Yang paling sering terlupa

TerlupaAkibatnya
Cron di CI3 masih jalanJob berjalan dua kali โ€” email ganda, tagihan ganda
Redaksi tidak diberi tahuPanel berubah tanpa peringatan; artikel gagal terbit
Dukungan pelanggan tidak diberi tahuTidak tahu harus menjawab apa
URL webhook Midtrans belum diarahkanPembayaran tidak tercatat
Sitemap lama masih diajukanGoogle merayapi URL yang sudah dialihkan
Alarm pemantauan masih menunjuk CI3Tidak ada yang memberi tahu saat Astro bermasalah
Aturan skip WAF webhook belum dipasangFase 6 โ€” pembayaran diblokir
Rentang IP Cloudflare belum dikunciFase 8 โ€” WAF bisa dilewati

Baris pertama adalah yang paling merusak dan paling tidak terlihat. Cron CI3 yang mengirim newsletter, menagih langganan, atau membersihkan sesi akan terus berjalan setelah cutover โ€” bersamaan dengan versi Astro-nya. Hasilnya email ganda ke seluruh basis pembaca, atau lebih buruk, penagihan ganda. Nonaktifkan crontab CI3 sebagai langkah eksplisit di runbook, bukan sebagai hal yang diingat seseorang.

Setelah cutover

WaktuPekerjaan
Hari 1โ€“3Pantau intensif; siapkan orang yang siaga
Minggu 1Tinjau Search Console harian
Minggu 2Turunkan kapasitas ECS ke ukuran yang sesuai data nyata
Minggu 4Bandingkan biaya: egress, RDS, ECS, sebelum vs sesudah
Minggu 6Kalau semua stabil: matikan CI3, simpan cadangannya
Bulan 3Baru jalankan migrasi skema yang merusak kompatibilitas
Bulan 6Arsipkan berkas yatim

Uji asap otomatis, dijalankan tiap deploy

#!/usr/bin/env bash
set -u
U=https://portal.contoh.id
gagal=0
cek() { printf '%-42s ' "$1"; if eval "$2"; then echo "OK"; else echo "GAGAL"; gagal=$((gagal+1)); fi; }

cek "beranda 200" \
  '[ "$(curl -s -o /dev/null -w %{http_code} $U/)" = 200 ]'

cek "artikel 200" \
  '[ "$(curl -s -o /dev/null -w %{http_code} $U/berita/artikel-uji)" = 200 ]'

cek "artikel ter-cache" \
  'curl -sI $U/berita/artikel-uji | grep -qi "cf-cache-status: \(HIT\|MISS\|EXPIRED\|STALE\)"'

cek "tidak ada Set-Cookie di halaman publik" \
  '! curl -sI $U/berita/artikel-uji | grep -qi set-cookie'

cek "premium tidak bocor tanpa sesi" \
  '[ "$(curl -s $U/berita/artikel-premium-uji | grep -c KALIMAT_PARAGRAF_KESEPULUH)" = 0 ]'

cek "akun tanpa sesi mengalihkan" \
  '[ "$(curl -s -o /dev/null -w %{http_code} $U/akun)" = 302 ]'

cek "URL lama dialihkan 301" \
  '[ "$(curl -s -o /dev/null -w %{http_code} $U/news/detail/4471)" = 301 ]'

cek "webhook menolak tanda tangan palsu" \
  '[ "$(curl -s -o /dev/null -w %{http_code} -X POST $U/api/midtrans-webhook \
        -H "Content-Type: application/json" -d "{\"order_id\":\"x\",\"status_code\":\"200\",\
        \"gross_amount\":\"1.00\",\"signature_key\":\"$(printf %0128d 0)\",\
        \"transaction_status\":\"settlement\",\"transaction_id\":\"x\",\"payment_type\":\"x\"}")" = 403 ]'

cek "sitemap berita valid" \
  'curl -s $U/sitemap-berita.xml | grep -q "<urlset"'

echo "Gagal: $gagal"; exit $((gagal > 0))

Latihan: tulis runbook cutover untuk portalmu sendiri dengan angka ambang yang konkret dan nama orang yang berwenang memutuskan rollback. Lalu latih rollback-nya di lingkungan uji dan ukur waktunya dengan stopwatch. Kalau lebih dari 60 detik, sederhanakan prosedurnya sampai tidak. Terakhir, jalankan skrip uji asap di atas dan pastikan semuanya OK sebelum menganggap persiapanmu selesai.

Rangkuman ini sengaja dipangkas ke bagian yang dipakai di roadmap. Buka sumber aslinya saat kamu butuh detail lengkap atau referensi parameter.