Upgrade to Pro — share decks privately, control downloads, hide ads and more …

ふつうのFeature Flag実践入門

Avatar for irof irof
May 30, 2026

ふつうのFeature Flag実践入門

JJUG CCC 2026 Spring 2026-05-30
https://ccc2026spring.java-users.jp/

Avatar for irof

irof

May 30, 2026

More Decks by irof

Other Decks in Programming

Transcript

  1. なにもの? • コードを変更せず動作を変更する仕組み • Feature Flag、フィーチャーフラグ ◦ たまにフューチャーフラグと言われたり ◦ 未来向いてて良いと思う

    • フラグと言ったりトグルと言ったりする ◦ 同じものだけど区別する派閥もある • 再ビルドや再デプロイをしないのが基本 ◦ デプロイとリリースを切り離すのに使う
  2. 評価タイミング • なし(マージ時) ◦ 変更したコードをマージしたら変わる • ビルド時 ◦ ビルド時に評価する •

    起動時 ◦ 起動時に一度だけ評価する • 実行時 ◦ 処理が実行されるたびにフラグを評価する
  3. 評価タイミングとFeature Flag • 実行時評価がいわゆるFeature Flag • 起動時に一度評価するものは再起動が必要になる ◦ そのためFeature Flagに含まないことが多い

    ◦ けど本セッションではFeature Flagの枠で扱います • マージ時はフラグ関係ないので違う • ビルド時はめちゃ広げればだけど、流石にFeature Flagとは 違うなーって。おもった。
  4. フラグをどう判定するか • true / false の値だけなら単に if で分岐すればOK • 三値以上持たせることも可能

    ◦ フラグって名前やめろ • 設定値以外(たとえばユーザーのロールなど)による分岐も 可能 • どういう判定をしたいかを目的と照らして考えます • Feature Flagライブラリはここにフォーカスしている • これも「柔軟な方がいい」ものでもない
  5. 補足: 柔軟性という毒 • 柔軟なのはいいこと ◦ とは限らない ◦ 柔軟性は不安定さにつながる ◦ (Java言語使いなら伝わる?)

    • 下手な柔軟性は期待に逆行する • Feature Flagは安定して動いて欲しい • 「Feature Flagのせいでトラブりました」←つらい ◦ こういうのが起こりづらい設計をしたい
  6. ここで挙げられているもの • Release Toggles: リリースフラグ • Experiment Toggles: 実験フラグ •

    Ops Toggles: 運用フラグ • Permission Toggles: 権限フラグ 出典: https://martinfowler.com/articles/feature-toggles.html 本セッションでは紹介に留めます。
  7. 注意: 「ぜんぶで4種類」ではない • 前図はlongevity × dynamism の2軸で整理したもの ◦ とうぜん、他の軸もありえる •

    境界は曲線かつ破線 ◦ 厳密な区切りではない、という意図的な表現 ◦ たぶん。知らんけど。 • 2軸は四象限図にしがちだが、四象限で描いてしまうと「4つ ですべて」に見えるミスリードにつながる
  8. Feature Flagが向かないもの • 恒久的に残りそうな分岐 ◦ 汎用的な仕組みではなく特化した設計が合う ◦ OpsやPermissionをどう捉えるかは検討課題 • 強い整合性が必要な複数システムの同時切り替え

    ◦ Feature Flagの工夫で乗り越えるのは至難の業 ◦ 後ほど解決案を紹介します • セキュリティ境界や権限制御の中核 ◦ 汎用的な仕組みでなく(以下略 • その他なにかしらの代替としての濫用
  9. いい塩梅で使おう • 対象を理解し、技術も理解し ◦ 必要な時に、必要なだけ。 • できたら苦労しない • 適切に使い分けるには知識と経験が要る ◦

    経験を積まないと分からない難しさも多い • やらないことはうまくならない ◦ やれるところから少しずつやっていこう ◦ 無理じゃない範囲で強引に使うのも一考
  10. 参考: 抽象ブランチとは • 変更を安全にmainブランチへ統合し続けるための手法 • コンフリクトやマージに伴うリスクを軽減する • 既存コードと新コードの間に抽象レイヤーを挟むなどし、両 者を共存させる •

    万能解ではなく、以下の問題を持ち込む。 ◦ 同じ目的のコードが重複する ▪ 静的解析に警告されることも ◦ 変更が差分にならずdiffでレビューできない
  11. やること application.yml 等のプロパティファイルでフラグ値を管理 し、Environment や @Value、 @ConditionalOnProperty で参照する。 これにより2つの切り替えが実現できる。 1.

    起動時にコンポーネントを差し換える 2. 実行時にフラグを参照して分岐する ただしどちらも変更は再起動が必要
  12. 2nd: コメント • フラグの管理はSpring Bootプロパティの管理に従う • 動的な変更への対応は難しい ◦ 再起動が必要 ◦

    変更は環境変数や起動時引数などを触る ◦ そのためデプロイとリリースが分離されない • フラグ値以外での判定は未解決 ◦ やるとしたら独自ロジック
  13. 3rd: コメント • 車輪の再発明でなくできた車輪を借りてこよう • Java以外でも使うならOpenFeatureは有力 ◦ SDKが利用可能なことが条件 • Providerの公開実装があれば楽できるかもだけど、なくても

    結構簡単に作れる • Provider差し替えやフラグ以外の条件での評価と言った車輪 が実装されているので再発明を避けられる • 本番で使用するなら何をBean定義するかとかちゃんと設計し よう
  14. OpenFeatureの直接使用を避けたい理由 • フラグキー(文字列)のハードコーディング ◦ typoのリスクがある ◦ 一覧化が別途必要になってくる ◦ 使用箇所を探すのがgrep •

    EvaluationContext の構築がノイジー ◦ 本来やりたい仕事ではない ◦ 分岐もそれなりにノイズなのに、より酷くなる • プロダクトコードの外部依存を局所化したい
  15. テストの考え方 1/2 • 分岐網羅はしておきたい ◦ どちらも本番で動作するコード ◦ 呼ばれないコードは壊れても気づけない • テストの重複は許容する

    ◦ むしろ自然なこと • 廃止予定の処理も最後までテストを維持する ◦ 切り替え後も切り戻し先として現役
  16. NGの理由 • Feature Flagに限った話でもない ◦ パスが4つあるのがつらい • Feature Flagの実装によっては異なる結果になることも当然 ある

    • 1リクエスト内で変わってしまうと再現しにくい不具合になる ◦ これが期待する動作であることはまずない
  17. 判定箇所と判定ロジックを分離する • 呼び出し側は「ONか?」を問い合わせるだけ • if (date > X && user.isBeta())

    のような判定ロ ジックを散らばらせない • 判定ロジックは1箇所(ラッパー/ルーター)に集約する • 高レベルAPIの実装箇所を用意しておくのが FeatureGate の狙いの一つ
  18. Kill Switch • すぐにOFFにできる状態にしてリリースする • OFF -> ON がすぐ切り替えられるなら、ON ->

    OFFも 理屈 上は すぐできる • データも含めると案外難しいことも多い
  19. DBマイグレーションとの兼ね合い • DBマイグレーションとFeature Flagは衝突しがち • これもFeature Flag固有の問題ではない ◦ リリースは常に切り戻しを想定すべき •

    Feature FlagはON/OFFが切り替わる前提 • 繰り返しになるが「ONで動くがOFFで動かない」は不可 • ずさんな移行が表面化しただけ
  20. 参考: Expand/Contract での安全な移行 破壊的変更を避け、各段で両方が動く 1. Expand: 新カラム追加(後方互換) 2. 両書き: 新旧両方に書く

    3. 読み先を新カラムへ切替(Feature Flagで制御) 4. Contract: 旧カラム削除(撤去とセット) 各段を個別にデプロイして切り戻せる状態を維持しながら進む
  21. 話したつもりのこと • Feature Flagは、デプロイとリリースを分ける実践的な道具 ◦ とはいえ一足飛びにそこに至るのは難しい ◦ なので使いながらレベルをあげていく • 実態はただの分岐なので雑に使うとすぐ負債になる

    • 目的に合わせて選び、撤去まで見据えて導入する • 価値の本丸は「リリースを扱いやすくすること」 ◦ リリースのハンドルをビジネスに渡すのを目指す ◦ それを支える仕組みをあたりまえにする
  22. 初めて学ぶ人 • 前提 ◦ Feature Flag未使用、未検討 ◦ featureブランチで開発している • まず1つのfeatureブランチを抽象ブランチで統合してみる

    ◦ コードが統合できなければFeature Flagに至らない • マージとリリースを切り離す選択肢を持つ ◦ デプロイとリリースの分離はその先にある
  23. Q2. 商用 vs 自前 商用サービスと自前実装はどう使い分ければよいですか? Experiment flag(sticky bucketing)や複雑なターゲティングが必 要になった時点で商用サービスが現実的な選択肢になります。 Release

    flagやOps flagだけなら自前実装+OpenFeatureで十分 なケースが多いです。最初から商用サービスを入れると「フラグ を使う習慣」より「ツールの習熟」が先になりがちなので、規模や 用途を見極めてから導入を検討するのがよいと思います。