📑

新卒エンジニアの最初の挑戦:Feature Flag を用いた Phased Rollout 実装

に公開

はじめに

※この記事は、「KNOWLEDGE WORK Blog Sprint」第7日目の記事になります。

株式会社ナレッジワークに2025年の4月に新卒でバックエンドエンジニアとして入社し、ナレッジワークの開発基盤となるシステム・機能を開発する Middleware Group に配属となりました Hasshi です。

今回は、私が Middleware Group の現場に配属されて初めて実装を行った機能でもある Feature Flag の Phased Rollout についてご紹介します!

本記事で触れる内容

  • Feature Flag とは?
  • Feature Flag による、Phased Rollout とは?
  • ナレッジワーク社内にあった Phased Rollout の課題とは?

背景・課題

Feature Flag とは?

ナレッジワークでは Feature Flag と呼ばれる仕組みを開発に利用しています。 Feature Flag とは、コード内に機能のオン・オフを制御するフラグを埋め込むことでアプリケーションの挙動を動的に制御する仕組みおよび開発手法のことです。これにより、開発中の新機能のリリースや変更を容易に行うことができます。

下記の例示のように、シンプルなif文によって Feature Flag のオン・オフによる挙動の違いをアプリケーションのコードで表現します。

if useExampleFeature {
    //Feature Flagの"useExampleFeature"がONの場合の処理
} else {
    //Feature Flagの"useExampleFeature"がOFFの場合の処理
}

Feature Flag のメリット

Feature Flag の利用には下記のメリットがあります。

  • 機能のリリースタイミングとコードのデプロイタイミングの分離
    新機能のコードを本番環境にデプロイしたとしても、Feature Flag を有効にしなければ機能が公開されることがありません。コードのデプロイを事前に行い、後日に新機能の公開を任意のタイミングで即座に反映させるという運用も可能です。
  • 機能リリースの影響範囲の制御
    特定の顧客ごとに Feature Flag の有効/無効を切り換えることにより、本番環境内でも影響範囲を絞りながら公開を行うことが可能です。
  • Kill Switchとしての役割
    仮に本番環境で有効化された新機能によって障害が発生した場合でも、対象の機能の Feature Flag を無効にすることで迅速に原因の機能を無効化することができます。

Phased Rollout とは?

ナレッジワークの Phased Rollout とは、非機能要件に関わる変更を段階的にリリースするためのフローです。 Phased Rollout によって、少数のテナントから段階的にリリースすることで変更の影響範囲を制御することができます。これは、テナント単位のカナリアリリースと考えることもできます。 Phased Rollout に必要なテナント単位のリリースのために内部で Feature Flag を利用しており、Feature Flag の「容易にリリースの影響範囲を制御できる」という利点を活かしたリリースフローとなっています。

例として全体で三つの Phase が定義されている場合 、全テナントを Phase1、 Phase2、 Phase3 の3つのテナントグループに分割し、新機能を公開する際には Phase1 → Phase2 → Phase3 の順に Feature Flag の有効化を行います。

以下のように各テナントが分割されている場合、まずPhase1で「株式会社 hoge」と「株式会社 piyo」のFeature Flag を有効化し、有効化による影響が無いことが確認できた場合にPhase2として「株式会社 fuga」の Feature Flag を有効化するという流れになります。

テナント名 Phase
株式会社 hoge Phase 1
株式会社 fuga Phase 2
株式会社 piyo Phase 1

ナレッジワークでの Phased Rollout の課題

今回の実装タスク以前の ナレッジワーク では、Phased Rollout のフロー自体はありましたがシステムによる管理・実行する仕組みは追い付いていませんでした。具体的に、Phased Rollout を行う際には、 Rollout Phase についてまとめられているスプレッドシートから対象の Rollout Phase に属するテナントのIDを抽出し、1テナントごとに Feature Flag を有効化する運用となっていました。

上記のように、Phased Rollout は人の判断と手による実行に依存した形で運用されていたため以下のようなリスクや非効率な手続きが存在していました。

  • 対象テナントを間違えるリスク
    こちらが最も重要な課題でした。 テナントIDを指定して Feature Flag を有効化する作業を人の手で行っていたため、ヒューマンエラーによるミスが発生しやすい状況にありました。例えば、本来 Phase1 で有効化すべきテナントの操作が漏れたり、ある Phase に偏って有効化されてしまったりする恐れがあります。これらは、Phased Rollout 本来のメリットである「影響範囲を小さく制御する」という価値を損なうリスクにつながります。さらに、テナント数は今後も増加することが前提であるため、このリスクが発生する可能性は将来的に一層高まると予想されました。

  • スプレッドシートに依存した Rollout Phase の管理
    各テナントがどの Rollout Phase に属するかの情報はスプレッドシートにしかなかったため、テナントが新規に作成された場合はスプレッドシートの情報も更新しなければなりませんでした。スプレッドシート内の情報の更新が漏れていた場合、新規に作成されたテナントのFeature Flagの有効化がPhased Rollout内で行われない可能性が存在しました。また、編集権限がある人であれば容易にスプレッドシートの内容を書き変えることができるため、意図していないRollout Phaseの変更が起こりやすい状態でもありました。

  • 必要以上に多い承認作業
    ナレッジワークでは、本番環境のテナントに対して Feature Flag の有効化操作やコマンドを実行する際には、申請と承認が必要です。そのため、テナント一つずつに対して Feature Flag を有効化していく際にはテナントの数だけ承認者が操作のレビューをする必要があり、操作の申請者・承認者両方に必要以上の時間と労力がかかっていました。

Phased Rolloutをシステムで管理する

上記で挙げたように、今までの Phased Rollout の管理・運用方法では様々なリスクが存在していたり、必要以上の作業コストがかかっていた部分がありました。これらの課題を解決し、Phased Rollout が安全に正しく運用され続けるために、Phased Rollout をシステムで管理・運用できる仕組みを実装しました。

Phased Rollout の実装

Phased Rollout をどのように実装したかについて説明します。大きく、 Rollout Phase の管理部分とPhased Rollout の実行部分の二つに分かれます。

Rollout Phase の管理

Rollout Phase の定義

Rollout Phase の定義は、以下のようなリレーショナルテーブルで定義して管理します。

id name is_default
0 unspecified false
1 Rollout Phase 1 false
2 Rollout Phase 2 false
3 Rollout Phase 3 true

基本的には、ID が1~4の各レコードが各 Rollout Phase に対応しています。 unspecified は、テナントが新規に作成された場合等に Rollout Phase が未設定であることを表すレコードです。

is_default の列は、一つの Rollout Phase のみ true となり、これが true である Rollout Phase がデフォルトの Rollout Phase として扱われます。デフォルトの Rollout Phase は、後述にあるように設定されている Rollout Phase が unspecified であるテナントの扱いを決定する際に使用されます。

テナントごとのRollout Phase

各テナントがどの Rollout Phase に所属するかは、各テナントのシステム設定の状態を表現するテーブルで管理します。イメージ的には以下のようになります。(以下の表だと、tenant1 が Phase2、 tenant2 が Phase3、tenant3 が Phase1 に属することとなります。)

tenant_id rollout_phase_id
1 2
2 3
3 1

新規にテナントが作成された場合の Rollout Phase の初期値は unspecified となります。しかし、日ごとのバッチ処理の際に Rollout Phase が unspecified のテナントに対してはデフォルトの Rollout Phase が設定される仕様としています。これにより、新規に作成されたテナントに対しての Rollout Phase の設定が漏れることを防ぐことができます。

Phased Rollout の実行

Phased Rollout の実行は以下の三つの引数を受け取り、行います。
引数: <feature flag> <rollout phase id> <dry run>

feature flagrollout phase idはそれぞれ有効化する Feature Flag と Rollout Phase に対応しています。また、実際の変更処理を伴わないdry runで行うかを指定することができるようにし、コマンドの実行結果が意図した通りであることを確認できるようにしています。

実行の内部処理自体はシンプルで、引数で指定された Rollout Phase であるテナントを取得し、取得したテナントすべてに対して Feature Flag を有効化します。

Phased Rollout を実装した結果

Phased Rollout をシステムで管理できるようにした今回の実装によって、以下のポジティブな結果を得ることができました。

  • 対象のテナントを間違えるリスクの軽減
    各 Rollout Phase のテナントグループはシステム上で管理できているため、Phased Rollout 実行時には有効化したいテナントグループ(Rollout Phase)を指定するだけで正しいテナントグループに対して Feature Flag の有効化を行うことができます。シンプルな対象指定方法への変化により、Phased Rollout の対象テナントを間違えるリスクを大きく減らすことができました。

  • スプレッドシートに依存しないRollout Phaseの管理
    スプレッドシートに依存しない形で、Rollout Phase の情報を管理することができるようになりました。仮にスプレッドシートの更新が漏れていたとしても新規のテナントに自動的に Rollout Phase が設定されるようになり、Phased Rollout の仕組みの中に自動的に組み込まれるようになりました。また、変更には承認が必要な本番環境で Rollout Phase の情報を管理することによって意図していない Rollout Phase の変更を起こりづらくすることができました。

  • Phased Rollout 実行手順の簡単化
    一つの Phase への Rollout を一度のコマンドで行えるため、必要な承認作業の数を減らすことができました。また、コマンドの引数もシンプルでわかりやすくなり、承認者がコマンド内容のレビューをしやすくなりました。

学び

新卒最初のタスクが Phased Rollout の実装でよかったこと

ナレッジワークに入社後バックエンドエンジニアとして私が担当した最初のエピックが この Phased Rollout の実装でした。今振り返ると、最初のタスクが Phased Rollout で良かったと、大きく二つの理由から思いました。

一つ目の理由は、実現したい機能がわかりやすいことです。 Feature Flag という背景知識は必要なものの、実現したいことの基本的な部分は Feature Flag の有効化をまとまったグループごとに行えるようにするというものです。そのため、実装に伴い必要なコードの修正等がなぜ必要なのかも自然と理解することができたため、エピック内で一貫して目的が明確な状態でモチベーション高く取り組むことができました。

二つ目の理由は、バックエンドの基礎的な仕組みについて触れることができたことです。これはナレッジワーク社内の開発環境による部分が大きいですが、Phased Rollout の実装を通してデータベースのマイグレーションからAPIの開発等のバックエンドの開発に必要な要素一通りに触れることができました。これにより、バックエンド開発の全体像を早期に掴めたり、チーム開発にあたり必要な基礎的な知識・認識を得ることができたのはバックエンドエンジニアとしてのスタートとして非常によかったです。

Phased Rolloutの今後の課題

今回の Phased Rollout の実装にはまだ様々な課題が残っています。例えば、今回の実装だけでは Phased Rollout で有効化する Rollout Phase の順番をコントロールすることはできていません。そのため、実行者のミス等により Phase1 へのロールアウトがされていないにもかかわらず Phase2 へのロールアウトが行われてしまったということが起こり得ます。また、上記に似た問題でもありますが、各 Feature Flag がどの Rollout Phase までロールアウトが行われているかもシステム上では確認することができません。これにより、 Phased Rollout の運用を行う上でまだシステム外の情報に依存しなければいけない部分が残っています。

最後に

Phased Rollout のシステム管理機能の実装によって、以前よりも正しく安全に Phased Rollout を行うことができるようになりました。しかし、さらに安全性を上げるために必要なことは残っていますので、実装を行った本人として責任を持って改善を続けていきたいと思います。

私の記事は以上となります!ここまで読んでいただきありがとうございました!
KNOWLEDGE WORK Blog Sprint、2週目最初である明日9/8の執筆者は私が所属する Middleware Group の兄貴的存在である、aitaさんです!
お楽しみに!

株式会社ナレッジワーク

Discussion