Rollback via feature flag adalah cara mematikan perilaku baru tanpa harus melakukan deploy ulang, selama fitur tersebut memang dirancang berada di balik flag. Ini berguna ketika rilis menyebabkan error rate naik, latency memburuk, antrean menumpuk, atau perilaku bisnis menyimpang, tetapi sistem lama masih tersedia dan aman digunakan.

Runbook ini ditujukan untuk tim backend, SRE, dan DevOps yang membutuhkan prosedur praktis saat rilis bermasalah. Fokusnya bukan sekadar “toggle off”, melainkan bagaimana mendesain flag agar bisa menjadi mekanisme rollback, metrik apa yang harus dipantau, kapan fitur harus dimatikan, dan bagaimana memastikan sistem benar-benar pulih setelah rollback.

1. Kapan Feature Flag Cocok untuk Rollback?

Feature flag efektif untuk rollback jika perubahan yang dirilis bisa dipisahkan dari deployment. Contohnya:

  • Endpoint memakai algoritma pricing baru, tetapi algoritma lama masih tersedia.
  • Worker memakai flow pemrosesan baru, tetapi bisa kembali ke flow lama.
  • UI atau API mengaktifkan field baru secara bertahap.
  • Integrasi dengan vendor baru bisa dialihkan kembali ke vendor lama.

Feature flag tidak cukup jika deployment sudah menjalankan migrasi database destruktif, menghapus kode lama, mengubah kontrak API secara tidak kompatibel, atau menulis data dalam format baru yang tidak bisa dibaca sistem lama. Untuk kasus seperti itu, rollback memerlukan strategi tambahan seperti backward-compatible migration, dual-read, dual-write yang dikontrol, atau data repair.

2. Prasyarat Desain Flag agar Bisa Menjadi Mekanisme Rollback

Feature flag yang aman untuk rollback harus didesain sebelum rilis. Flag yang dibuat asal-asalan sering gagal saat insiden karena tidak jelas pemiliknya, tidak punya metrik, atau hanya menutup sebagian jalur eksekusi.

Gunakan flag di boundary yang tepat

Letakkan evaluasi flag pada boundary yang stabil: service layer, handler API, job processor, atau adapter integrasi. Hindari menyebar pengecekan flag di banyak fungsi kecil tanpa pola yang jelas karena akan sulit memastikan semua jalur benar-benar kembali ke perilaku lama.

// Contoh sederhana di service layer backend
function canUseCheckoutV2(flags, user) {
  const flag = flags.get("checkout_v2");

  if (!flag || flag.enabled !== true) return false;
  if (flag.killSwitch === true) return false;
  if (flag.allowList?.includes(user.id)) return true;

  return flag.rolloutPercentage > bucket(user.id, flag.key);
}

async function createCheckoutSession(ctx, request) {
  if (canUseCheckoutV2(ctx.flags, ctx.user)) {
    return checkoutV2.createSession(request);
  }

  return checkoutV1.createSession(request);
}

Contoh di atas menunjukkan beberapa prinsip penting: default aman adalah off, ada kill switch eksplisit, rollout bisa dibatasi, dan fallback lama masih tersedia.

Tentukan owner, expiry, dan dokumentasi singkat

Setiap flag yang dipakai untuk rilis harus memiliki:

  • Owner: tim atau individu yang bisa mengambil keputusan saat insiden.
  • Tujuan: fitur atau perubahan apa yang dikendalikan.
  • Default behavior: apa yang terjadi jika sistem flag tidak tersedia.
  • Expiry date: kapan flag harus dihapus setelah stabil.
  • Link runbook: instruksi toggle, dashboard, dan validasi.

Tanpa metadata ini, tim on-call sering membuang waktu mencari tahu apakah aman mematikan flag tertentu.

Pastikan fallback benar-benar masih diuji

Rollback via feature flag hanya bekerja jika jalur lama masih valid. Jalur fallback perlu masuk automated test, smoke test, atau minimal diuji sebelum rollout. Kesalahan umum adalah membiarkan kode lama tetap ada tetapi tidak pernah diuji setelah perubahan skema, dependency, atau kontrak API.

Hindari flag yang mengubah data secara tidak kompatibel

Jika fitur baru menulis data dengan format baru, pastikan sistem lama masih bisa membacanya. Jika tidak, mematikan flag bisa membuat request berikutnya gagal karena data yang sudah terlanjur ditulis tidak cocok dengan flow lama.

Catatan: untuk perubahan database, gunakan migrasi bertahap: tambah kolom dulu, deploy kode yang kompatibel, aktifkan flag, validasi, lalu bersihkan struktur lama setelah aman. Jangan menggabungkan perubahan destruktif dengan rilis yang masih eksperimental.

3. Observability yang Wajib Dipantau

Feature flag sebagai rollback hanya berguna jika tim tahu kapan harus memakainya. Karena itu, dashboard dan alert harus memantau metrik yang spesifik terhadap fitur, bukan hanya metrik global aplikasi.

Metrik teknis

  • Error rate per fitur atau endpoint: bedakan error pada flow baru dan flow lama.
  • Latency percentile: pantau p95 atau p99 untuk request yang melewati flag.
  • Throughput: request per detik, job per menit, atau event yang diproses.
  • Queue depth dan lag: penting untuk worker, stream processing, dan async jobs.
  • Dependency error: kegagalan database, cache, message broker, atau vendor eksternal.
  • Resource saturation: CPU, memory, connection pool, thread pool, disk I/O jika relevan.

Metrik bisnis atau domain

  • Rasio checkout berhasil versus gagal.
  • Jumlah pembayaran tertunda atau duplikat.
  • Penurunan konversi pada segmen yang mendapat fitur baru.
  • Jumlah order, invoice, atau transaksi yang masuk status tidak normal.

Metrik bisnis penting karena tidak semua bug muncul sebagai HTTP 500. Fitur bisa “sukses” secara teknis tetapi menghasilkan perhitungan salah, status keliru, atau pengalaman pengguna yang buruk.

Log dan tracing

Sertakan informasi flag pada log dan trace, misalnya nama flag, variasi yang dipilih, dan versi kode. Ini membantu membandingkan request yang melewati flow baru dengan flow lama.

{
  "event": "checkout_session_created",
  "request_id": "req_123",
  "feature_flag": "checkout_v2",
  "flag_variant": "enabled",
  "user_segment": "beta",
  "latency_ms": 342
}

Jangan mencatat data sensitif hanya demi debugging. Gunakan ID korelasi dan metadata teknis yang cukup untuk investigasi.

4. Runbook Triase saat Rilis Bermasalah

Bagian ini bisa dijadikan prosedur on-call. Sesuaikan ambang batas metrik dengan karakteristik sistem masing-masing.

Langkah 1: Konfirmasi gejala dan cakupan dampak

  1. Periksa alert utama: error rate, latency, queue lag, atau metrik bisnis.
  2. Bandingkan periode sebelum dan sesudah rollout.
  3. Segmentasikan berdasarkan flag: enabled, disabled, allowlist, percentage rollout, region, tenant, atau versi aplikasi.
  4. Pastikan apakah masalah hanya terjadi pada jalur fitur baru.

Jika masalah juga terjadi pada jalur lama, kemungkinan penyebabnya bukan hanya fitur baru. Misalnya dependency down, migrasi database bermasalah, atau kapasitas infrastruktur tidak cukup.

Langkah 2: Cek perubahan terakhir

  • Deployment terakhir dan commit terkait.
  • Perubahan konfigurasi, secret, environment variable, atau routing.
  • Migrasi database yang baru berjalan.
  • Perubahan dependency eksternal atau kebijakan rate limit vendor.
  • Perubahan rule feature flag: percentage, segment, targeting, atau default value.

Langkah 3: Tentukan tindakan mitigasi

Pilih tindakan paling cepat yang menurunkan dampak dengan risiko terkecil:

  • Turunkan rollout percentage jika dampak masih terbatas dan ingin mempertahankan observasi.
  • Matikan flag sepenuhnya jika error meningkat tajam, data berisiko salah, atau pelanggan terdampak nyata.
  • Aktifkan kill switch untuk menghentikan side effect seperti pemanggilan vendor, penulisan event, atau job baru.
  • Rollback deployment jika kode baru merusak jalur lama atau flag tidak menutup seluruh perubahan.

5. Kriteria Mematikan Fitur

Keputusan mematikan flag sebaiknya tidak bergantung pada intuisi semata. Buat kriteria eksplisit sebelum rilis agar on-call tidak perlu berdebat saat tekanan tinggi.

  • Error rate flow baru melewati ambang yang disepakati dan lebih buruk dibanding baseline.
  • Latency p95 atau p99 flow baru meningkat signifikan dan memengaruhi SLO.
  • Queue lag terus naik setelah fitur aktif.
  • Ada indikasi data corruption, transaksi duplikat, salah hitung harga, atau status bisnis tidak konsisten.
  • Dependency eksternal menerima beban berlebih atau mulai menolak request.
  • Tim tidak bisa menjelaskan penyebab dalam waktu triase yang disepakati.

Prinsip operasional: jika ada risiko data salah atau transaksi finansial keliru, prioritaskan mematikan fitur lebih dulu. Investigasi mendalam bisa dilakukan setelah dampak berhenti.

6. Eksekusi Rollback via Feature Flag

Langkah eksekusi harus singkat, terverifikasi, dan tercatat.

  1. Umumkan niat mitigasi di kanal insiden: “Mematikan flag checkout_v2 untuk menghentikan kenaikan error rate.”
  2. Catat waktu mulai agar mudah dikorelasikan dengan grafik.
  3. Ubah flag dari enabled ke disabled, atau ubah rollout percentage ke 0.
  4. Pastikan propagasi konfigurasi selesai. Beberapa sistem flag memiliki caching; jangan asumsikan perubahan instan di semua instance.
  5. Verifikasi dari aplikasi, bukan hanya UI pengelola flag. Cek log, trace, atau endpoint diagnostik internal jika tersedia.
  6. Pantau metrik pemulihan selama beberapa interval observasi.

Contoh checklist eksekusi

  • [ ] Incident commander atau on-call menyetujui mitigasi.
  • [ ] Nama flag dan environment benar, misalnya production, bukan staging.
  • [ ] Nilai flag diubah ke disabled atau rollout 0%.
  • [ ] Perubahan tercatat di audit log atau tiket insiden.
  • [ ] Log aplikasi menunjukkan request baru memakai jalur fallback.
  • [ ] Error rate dan latency mulai kembali ke baseline.
  • [ ] Tidak ada backlog baru di queue terkait.
  • [ ] Stakeholder diberi update singkat.

7. Validasi Setelah Rollback

Mematikan flag bukan akhir dari insiden. Tim harus memastikan bahwa sistem pulih dan tidak meninggalkan efek samping.

Validasi teknis

  • Bandingkan error rate sebelum dan sesudah waktu toggle.
  • Pastikan latency kembali mendekati baseline.
  • Periksa log untuk memastikan tidak ada request baru yang masih melewati flow bermasalah.
  • Cek queue: apakah backlog berhenti naik dan mulai terkuras.
  • Periksa retry storm. Setelah fitur dimatikan, retry dari kegagalan sebelumnya bisa tetap membebani sistem.

Validasi data dan bisnis

  • Ambil sampel transaksi atau event selama periode insiden.
  • Cari data dengan status tidak normal, duplikat, atau field kosong.
  • Tentukan apakah perlu data repair, replay event, refund, atau rekonsiliasi manual.
  • Konfirmasi dengan tim produk atau operasi jika ada dampak ke pengguna.

Jika fitur baru sudah menulis data yang tidak kompatibel, rollback flag bisa menghentikan kerusakan baru tetapi tidak otomatis memperbaiki data lama. Masukkan pekerjaan pemulihan data ke rencana insiden.

8. Komunikasi Insiden

Komunikasi yang baik mengurangi kebingungan dan mencegah keputusan paralel yang saling bertentangan. Gunakan satu kanal insiden dan satu orang pengarah jika insiden cukup besar.

Format update singkat

Status: mitigasi berjalan
Dampak: checkout error meningkat pada pengguna yang mendapat checkout_v2
Aksi: flag checkout_v2 dimatikan di production pada 10:42 WIB
Validasi: error rate mulai turun, queue payment masih dipantau
Langkah berikutnya: cek transaksi selama 10:10-10:42 dan siapkan data repair bila perlu

Informasi yang perlu dicatat

  • Waktu gejala pertama terdeteksi.
  • Waktu keputusan rollback.
  • Waktu flag dimatikan.
  • Waktu metrik kembali normal.
  • Siapa yang mengubah flag dan nilai sebelum/sesudah.
  • Dampak pengguna, dampak bisnis, dan cakupan data.

Catatan ini membantu postmortem dan audit. Hindari menyalahkan individu; fokus pada fakta teknis dan keputusan operasional.

9. Postmortem Ringan Setelah Sistem Stabil

Untuk insiden kecil, postmortem tidak harus panjang. Namun tetap perlu menjawab pertanyaan inti agar rilis berikutnya lebih aman.

  • Apa yang berubah? Commit, konfigurasi, flag rule, migrasi, atau dependency.
  • Mengapa masalah tidak tertangkap sebelum produksi? Gap test, staging tidak representatif, kurang load test, atau tidak ada metrik spesifik.
  • Mengapa feature flag berhasil atau gagal sebagai rollback? Apakah fallback lengkap? Apakah propagasi lambat? Apakah ada side effect yang tetap berjalan?
  • Berapa lama deteksi dan mitigasi? Catat waktu dari deploy ke alert, alert ke keputusan, dan keputusan ke pemulihan.
  • Apa tindakan pencegahan yang konkret? Tambahkan owner, dashboard, test, guardrail, atau ubah pola migrasi.

Hasil postmortem harus menghasilkan action item yang bisa dieksekusi, bukan hanya kesimpulan umum seperti “perlu lebih hati-hati”.

10. Tindakan Pencegahan untuk Rilis Berikutnya

  • Canary rollout: mulai dari internal user, allowlist, tenant kecil, atau persentase rendah sebelum semua pengguna.
  • Predefined rollback criteria: tetapkan metrik dan ambang sebelum rilis.
  • Dashboard per flag: tampilkan metrik flow baru versus flow lama.
  • Audit flag: review flag aktif secara berkala dan hapus yang sudah tidak diperlukan.
  • Backward-compatible migration: jangan membuat rollback bergantung pada migrasi destruktif.
  • Automated smoke test: uji jalur enabled dan disabled setelah deploy.
  • Fail-safe default: jika service feature flag gagal, pilih perilaku yang paling aman untuk sistem.
  • Load testing selektif: uji bagian yang berubah, terutama query baru, integrasi eksternal, dan job asinkron.

11. Anti-pattern yang Harus Dihindari

  • Flag tanpa owner: saat insiden, tidak ada yang yakin apakah aman dimatikan.
  • Flag permanen: kode dipenuhi cabang lama dan baru sehingga sulit diuji dan dirawat.
  • Metrik tidak spesifik: hanya memantau error rate global tanpa membedakan flow yang terkena flag.
  • Flag hanya di frontend: backend tetap menjalankan side effect berbahaya meski tombol UI disembunyikan.
  • Fallback tidak diuji: jalur lama rusak karena dependency, skema, atau kontrak berubah.
  • Toggle tanpa audit: perubahan flag tidak tercatat sehingga timeline insiden kabur.
  • Flag mengontrol terlalu banyak hal: satu toggle mengubah algoritma, migrasi data, routing vendor, dan format response sekaligus.

12. Checklist Ringkas Sebelum Rilis

  • [ ] Flag memiliki owner, deskripsi, expiry date, dan link runbook.
  • [ ] Jalur enabled dan disabled sudah diuji.
  • [ ] Dashboard membedakan metrik flow baru dan flow lama.
  • [ ] Alert mencakup error, latency, queue, dependency, dan metrik bisnis kritis.
  • [ ] Kriteria rollback sudah disepakati.
  • [ ] Perubahan database kompatibel dengan rollback.
  • [ ] Kill switch tersedia untuk side effect berisiko.
  • [ ] Tim on-call tahu cara mengubah flag dan memvalidasinya.

Kesimpulan

Rollback via feature flag dapat mempercepat mitigasi rilis bermasalah, tetapi hanya jika flag didesain sebagai kontrol operasional, bukan sekadar sakelar eksperimen. Pastikan fallback masih sehat, metrik cukup spesifik, owner jelas, dan prosedur insiden sudah dilatih.

Runbook yang baik membantu tim mengambil keputusan cepat: triase dampak, matikan fitur jika melewati kriteria risiko, validasi pemulihan, komunikasikan status, lalu lakukan postmortem ringan. Dengan disiplin ini, feature flag menjadi bagian dari strategi rilis yang lebih aman dan terukur.