Apa itu feature flag: panduan lengkap untuk developer

Summary

Feature flag adalah pernyataan if yang jawabannya dari config, bukan hardcoded. Mereka memungkinkan merge aman, rollout bertahap, dan kill switch cepat. Tapi 200 flag dalam satu repo menciptakan technical debt. Panduan ini mencakup tipe flag, rollout aman, pembersihan flag, dan kapan melewatinya.

Engineer desk with a row of physical toggle switches beside a laptop

Apa itu feature flag

Sebuah feature flag adalah kondisional dalam kode Anda yang memutuskan saat runtime apakah sepotong perilaku aktif atau tidak, tanpa deploy baru. Itu seluruh idenya. Dalam praktiknya? Sebuah pernyataan if yang jawabannya berasal dari konfigurasi, baris database, atau layanan flag alih-alih dikodekan secara langsung.

Konsepnya sederhana. Hidup dengan 200 dari mereka dalam satu repository tidak, dan bagian kedua itu yang benar-benar dibahas panduan ini. Semakin besar tim Anda, semakin kompleks situasinya menjadi. Itulah mengapa beberapa tim besar telah mengembangkan proses formal dan tools dedicated untuk mengelola flags secara efisien pada skala besar. Tanpa investasi dalam proses dan tooling yang tepat, repository dengan banyak flags menjadi tidak terkelola dan sulit dipelihara.

Bagaimana bentuk feature flag dalam kode?

Berikut adalah versi yang paling berguna sekalipun:

if (flags.isEnabled("new-checkout", { userId })) {
  return renderNewCheckout();
}
return renderOldCheckout();

Kedua jalur kode dikirim dalam build yang sama. Nilai flag tinggal di tempat yang dapat Anda ubah tanpa deploy ulang: variabel lingkungan, file JSON, tabel, atau layanan yang dihosting. Ubah nilainya, dan perilaku berubah pada evaluasi berikutnya.

Pemisahan itu adalah intinya. Deployment adalah menempatkan kode di server. Rilis adalah membiarkan pengguna melihatnya. Flag memisahkan kedua peristiwa tersebut, jadi merge ke main tidak lagi berarti "semua orang mendapatkan ini sekarang."

Hand flipping a single toggle switch with a green indicator light

Mengapa tim menggunakan feature flag?

Tiga alasan muncul berulang kali dalam tim nyata yang terdiri dari 5 hingga 50 engineer.

Tidak ada dari ini yang memerlukan vendor. Flag dapat berupa boolean dalam tabel config. Lewati platform sampai Anda memerlukan percentage rollouts, audit trails, atau non-engineer yang mengubah-ubah hal.

Apa empat jenis feature flag?

Artikel feature toggles Pete Hodgson yang banyak dikutip di situs Martin Fowler mengurutkan flag berdasarkan berapa lama mereka hidup dan seberapa sering keputusan berubah. Kategorinya masih merupakan model mental yang paling jelas.

Kolom lifespan paling penting. Flag rilis yang melampaui rilinya adalah bug yang belum Anda temukan. Flag permission yang dihapus dalam sprint pembersihan adalah outage yang belum Anda alami.

Namai dan beri label tipenya saat membuat flag. Enam bulan kemudian, tidak ada yang ingat kategori apa "new-nav-v2". Ini adalah kesalahan umum dan menyebabkan confusion serius di kemudian hari bagi seluruh tim.

Team planning grid of sticky notes grouped by category

Bagaimana cara merilis flag tanpa melukai pengguna?

Urutan yang membosankan paling berhasil.

  1. Kirim kode dengan flag mati. Verifikasi tidak ada yang berubah.

  2. Aktifkan untuk tim Anda sendiri dalam production. Gunakan selama satu hari.

  3. Aktifkan untuk 1% hingga 5% pengguna, sticky berdasarkan user ID jadi tidak ada yang beralih antar varian tengah-sesi.

  4. Perhatikan error rate, latency, dan satu metrik bisnis. Putuskan ambang batas sebelum Anda mulai, bukan saat menatap dashboard.

  5. Ramp ke 100%, tunggu periode yang ditentukan, lalu hapus flag.

Langkah lima adalah yang dilewati tim. Kami akan melihat mengapa itu lebih mahal daripada yang Anda pikirkan.

Catatan praktis tentang evaluasi: buat flag reads murah dan failure-safe. Jika layanan flag sedang down, kode Anda memerlukan default. Pilih default per flag, dengan tujuan. Kill switch harus gagal ke "safe," sementara fitur baru harus gagal ke "off."

Mengapa feature flag menjadi technical debt?

Setiap flag adalah fork dalam kode Anda. Dua flag membuat empat jalur yang mungkin, sepuluh flag membuat 1.024, dan Anda hampir pasti menguji segelintir dari mereka. Panduan teknis GrowthBook tentang flag debt mengutip penelitian menunjukkan bahwa sekitar 75% komponen toggle masih ada di codebase hingga 49 minggu setelah diperkenalkan, meskipun sebagian besar developer mengatakan mereka berencana menghapusnya.

Hodgson mengatakannya dengan baik dalam artikel Fowler yang sama: tim yang cerdik memperlakukan toggle sebagai inventory dengan carrying cost, dan bekerja untuk menjaga inventory itu tetap rendah.

Kisah horror klasik adalah Knight Capital pada 2012. Flag fitur yang pensiun digunakan kembali untuk perilaku baru sementara kode lama masih duduk di satu server. Ketidaksesuaian itu berkontribusi pada sekitar $460 juta kerugian dalam kurang dari satu jam. Flag basi Anda mungkin tidak akan melakukan itu. Ini akan melakukan sesuatu yang lebih senyap: refactor yang memecahkan branch yang tidak ada orang ketahui ada, atau hire baru menghabiskan sore mencari tahu jalur checkout mana yang real.

Dusty shelf of forgotten boxes and old switches

Bagaimana cara menemukan setiap flag dalam codebase yang ada?

Ini adalah pertanyaan yang vendor docs lewatkan, dan ini di mana sebagian besar tim terjebak. Dashboard flag memberi tahu Anda apa yang dikonfigurasi. Itu tidak memberitahu Anda di mana setiap flag dibaca dalam kode, atau apakah jalur kode di balik flag "off" masih dapat dijangkau.

Mulai dengan pendekatan murah:

# setiap kunci flag literal dibaca melalui wrapper Anda
rg -n 'isEnabled\("' src/ | sort

# flag didefinisikan tetapi tidak pernah direferensikan
comm -23 <(jq -r 'keys[]' flags.json | sort) \\
         <(rg -o 'isEnabled\("([^\"]+)\"' -r '$1' src/ | sort -u)

Ini rusak dengan cepat. Kunci flag yang dibangun dari string concatenation tidak muncul dalam grep. Flag yang dilewatkan melalui helper functions menyembunyikan call sites mereka. Monorepos dan pengaturan multi-repo mengalikan masalah, karena kunci yang sama dapat dibaca oleh tiga layanan.

Di sinilah membaca kode dengan tooling membantu. Tools code search yang memahami repo Anda dapat menjawab "di mana new-checkout dievaluasi, dan apa yang bergantung pada hasilnya?" dalam satu query alih-alih sore grep. Cursor dan GitHub Copilot menangani ini secara wajar dalam satu repo. Di seluruh beberapa repo, Anda memerlukan index yang mencakup semua repo, yang merupakan kasus yang kami bangun codebasechat untuk.

Seperti apa proses pembersihan flag yang wajar?

Perlakukan penghapusan sebagai bagian dari pekerjaan, bukan tugas untuk nanti. Ini membutuhkan disiplin dan proses yang jelas dari awal bagi tim Anda untuk mencegah akumulasi flags lama.

Static analysis membantu di sini juga. Tools seperti CodeScene dapat menunjukkan file mana yang membawa logika kondisional yang paling kusut, yang biasanya di mana flag lama berkumpul. SonarQube menandai kode yang tidak dapat dijangkau dan mati setelah Anda menghapus pemeriksaan.

Bagaimana cara menguji kode yang duduk di belakang flag?

Testing adalah bagian yang tidak ada yang menganggarkan. Dengan dua jalur per flag, suite test Anda harus menutupi keduanya, setidaknya untuk flag yang menjaga perilaku berisiko.

Pertahankan praktis. Test on dan off states dari setiap release flag dalam unit tests, dengan inject nilai flag alih-alih membaca layanan live. Jalankan satu suite end-to-end terhadap konfigurasi production default, karena itu yang didapat pengguna hari ini. Kemudian jalankan pass kedua dengan flag on untuk fitur yang akan Anda rilis.

Jangan coba test setiap kombinasi. Dengan sepuluh flag Anda tidak dapat. Sebagai gantinya, jaga flag independen: flag yang mengubah perilaku hanya ketika flag lain juga on adalah design smell, dan itu adalah hal pertama untuk dilepas.

Apa yang salah dipahami junior tentang flag?

Junior cenderung membuat tiga kesalahan yang sama, dan masing-masing murah untuk dicegah dalam review.

Dua minggu pertama hire baru adalah tepat ketika mereka menjalankan flag lama tanpa pemilik. Registry flag pendek, dengan tipe, pemilik, dan tanggal penghapusan untuk setiap entri, menghemat beberapa jam bertanya-tanya.

Kapan Anda harus melewati feature flag?

Flag tidak gratis, jadi lewatkan mereka ketika:

Dan gunakan tanpa ragu ketika perubahan berisiko, user-facing, dan sulit dibalik dengan deploy ulang. Payment flows, auth changes, dan apa pun dengan data migration di belakangnya semua memenuhi syarat.

Apa yang benar-benar kami lakukan pada tim sepuluh orang

Mulai dengan boolean dalam config dan satu wrapper function, sehingga setiap pembacaan flag melewati satu tempat. Titik choke point tunggal itu membuat daftar flag greppable, auditable, dan mudah untuk migrate ke layanan yang dihosting nanti.

Beri label setiap flag berdasarkan tipe, beri pemilik, dan buat ticket penghapusan pada hari pertama. Review daftar bulanan selama sepuluh menit. Hapus flag yang telah 100% selama dua minggu.

Sebuah feature flag adalah pinjaman. Ambil ketika itu menyelamatkan Anda dari rilis yang berisiko, dan bayar kembali sebelum bunga muncul dalam refactor berikutnya.

Frequently asked questions

Apa itu feature flag?
Feature flag adalah kondisional dalam kode yang memutuskan saat runtime apakah fitur aktif tanpa deploy baru. Jawabannya berasal dari config atau database, bukan hardcoded.
Apa empat jenis feature flag?
Release (hari-minggu), Experiment (berminggu-minggu), Ops (jam-selamanya), dan Permission (bulan-tahun). Masing-masing dibedakan oleh lifespan dan frekuensi perubahan.
Mengapa feature flag menjadi technical debt?
Setiap flag adalah fork dalam kode. 10 flag = 1.024 jalur kode yang mungkin. 75% toggle masih ada di codebase 49 minggu setelah ditambahkan, menciptakan beban pemeliharaan.
Bagaimana cara menghapus flag dengan aman?
Buat ticket penghapusan dari hari pertama. Hapus dalam dua PR: hapus pemeriksaan dulu, lalu branch mati. Tambahkan time bomb test untuk release flags. Batas total untuk inventory rendah.
Kapan tidak boleh menggunakan feature flag?
Lewati flag untuk perubahan kecil yang mudah dibalik tanpa deploy. Jangan gunakan jika ada perubahan schema database. Perbaiki proses penghapusan terlebih dahulu jika tim tidak memilikinya.
Bagaimana cara menemukan semua flag dalam codebase?
Gunakan ripgrep untuk menemukan literal flag keys. Tools code search yang memahami repo dapat menjawab di mana flag dievaluasi dan dependensinya. Cursor dan GitHub Copilot menangani satu repo dengan baik.
Apa yang dimaksud dengan failing safely untuk flag?
Kill switch harus fail ke 'safe' (off). Fitur baru harus fail ke 'off'. Tentukan default per flag dengan tujuan jelas untuk mencegah masalah jika layanan flag down.