こんにちは、バックエンドエンジニアの @kumackey です。
『スタディサプリ』では、新機能の段階的リリースを支える仕組みとして、内製の Feature toggles 基盤「Darklaunch v2」を運用しています。本記事では、Darklaunch v2 が提供する機能群と改善の進め方について紹介します。
概要
Feature toggles とは
Feature toggles とは、コードのデプロイとリリースを分離する仕組みです。
通常の開発では、コードをデプロイするとそのまま新機能がリリースされます。デプロイとリリースが同時に発生するため、もし問題があった場合はコードを再デプロイして戻す必要があり、all-or-nothing なリスクの高いリリースになりがちです。

Feature toggles を導入すると、コードのデプロイと新機能のリリースは独立して行われます。コード上で if 分岐を書いておき、管理画面でトグルを切り替えるだけで制御できます。デプロイなしに任意の粒度で少しずつリリースしたり、問題があればすぐに戻したりできます。

Darklaunch v2 とは
Darklaunch v2 は、この Feature toggles を実現するための社内サービスです。以前は Rails アプリケーションの Ruby モジュールとして提供されていましたが、現在は Go のマイクロサービスとしてフルスクラッチで再構築されています。
Darklaunch v2 では、リリースを制御する単位を「キー」と呼びます。キーは新機能ごとに作成し、管理画面から設定を変更することでリリースを制御します。
開発者は SDK を使って、アプリケーションコードに if 分岐を書くだけで Feature toggles を利用できます。以下は Ruby SDK の例です。
if DarklaunchV2Client.variation('enable-new-feature', 'User.id', current_user.id, num_retries: 2) # 新機能の処理 else # 既存の処理 end
variation メソッドは、キー名と identifier(ユーザーを特定する情報)を受け取ります。管理画面での設定に基づいて true または false を返し、この結果で新機能の公開・非公開を制御できます。

Darklaunch v2 の全体像を以下に示します。

機能群
ここからは、Darklaunch v2 が提供する機能群を紹介します。それぞれ、どのような課題があり、どう解決しているかを説明します。
リリース済みキーの Slack リマインド
課題
Feature toggles を使った新機能のリリースが完了した後、キーがそのまま放置されてしまうことがあります。リリース済みのキーが残り続けると、以下の問題が発生します。
- 開発者にとっては、コード上の不要な分岐が技術的負債になる
- Darklaunch v2 基盤側としては、キー数やリクエスト数が増加し続ける
ちなみに Microsoft Office では約 12,000 もの Feature flags が存在するそうで、キーの放置は広く知られた課題です。
解決策
Argo CronWorkflow で定期実行されるジョブが、30日以上更新がないリリース済みのキーを検出し、Slack で通知します。

通知メッセージには、キー名や前回更新からの経過日数、管理画面へのリンクが含まれます。さらに Claude Code Action によるキーの削除 PR 自動作成リンクも付いています。

リクエスト数と最後にリクエストされた日時
課題
前述のリマインドでキーの放置に気づいた後、実際に削除してよいかの判断材料が必要です。「本当にもう使われていないのか?」が分からないと、削除に踏み切れません。
解決策
Darklaunch v2 API では、variation リクエストのたびに Datadog StatsD でメトリクスを記録しています。管理画面のキー詳細ページには、このメトリクスを利用した 2 つの情報が表示されます。
- リクエスト数のグラフ: Datadog の iframe を埋め込み、リクエスト数の推移をグラフで表示
- 最後に使われたとき: Datadog API を使って、最後にリクエストがあった時期を算出

この情報があることで、キーを削除する際に「最後に使われたのが約 3 ヶ月前なら、もう消して大丈夫だろう」と安心して判断できるようになります。
Owner team によるフィルタリング
課題
Darklaunch v2 のキーは組織全体で共有されているため、一覧には全チームのキーが混在して表示されます。キーの数は現在 100 個以上あり、自チーム関連のキーを探すのが大変になっていました。

解決策
一覧ページに Owner team のドロップダウンフィルターを設けています。チームを選択すると、そのチームが管理するキーだけに絞り込まれます。自チームのキーの状態をすばやく把握でき、他チームのキーに埋もれることがなくなりました。

Ruby SDK での Fail-safe 機能
課題
Darklaunch v2 はさまざまなサービスで使われており、停止するとサービス全体へ障害が波及しかねません。

解決策
Ruby SDK では、API へのリクエストが失敗した場合に false を返すことで安全側に倒す設計です。variation() が true を返すと新機能が有効になるため、エラー時に false を返せば「意図せず新機能が出てしまう」事故を防げます。

Ruby SDK でのテストの stub ライブラリ
課題
Darklaunch v2 を利用するアプリケーションのテストを書くには工夫が必要でした。DarklaunchV2Client のメソッドを直接 stub するか、HTTP リクエストを stub しなければなりません。
# DarklaunchV2Client を直接 stub する場合 allow(DarklaunchV2Client).to receive(:variation) .with('enable-new-feature', 'User.id', user.id, num_retries: 2) .and_return(true) # HTTP リクエストを stub する場合 stub_request(:get, %r{/variation\?.*key=enable-new-feature}) .to_return(status: 200, body: { variation: true }.to_json)
引数の順序やクエリパラメータの形式を正確に合わせる必要があり、テストが書きにくいという声がありました。
解決策
stub_darklaunch_v2 ヘルパーメソッドを提供し、テストでの利用を簡単にしています。管理画面での設定を模倣する設計で、キー、always_true、identifiers を指定するだけで stub を設定できます。
# 常に true を返す key を stub stub_darklaunch_v2('enable-new-feature', true) # 特定の identifier に対してのみ true を返す key を stub stub_darklaunch_v2( 'enable-new-feature', false, { 'User.id' => ['user-id-1', 'user-id-2'] } )
always_true が true の場合はどの identifier でも true を返します。false の場合は identifiers に指定された identifier のみ true を返します。管理画面での設定と同じ概念で stub を設定できるため、直感的にテストを書けます。
内部では DarklaunchV2Client::Mock::Server クラスが管理画面の挙動をシミュレートしています。variation をはじめとするすべてのメソッドに対応しています。
改善の進め方
ここまで紹介してきた機能群は、一度作って終わりではなく、利用者からのフィードバックを受けて継続的に改善してきたものです。ここでは、その進め方を紹介します。
Slack サポートチャンネル
Darklaunch v2 には専用の Slack チャンネルがあり、利用者とのコミュニケーションの場として機能しています。チャンネルでは主に以下の 3 種類のやり取りが行われています。
- 問い合わせ
- 要望
- 機能追加・改善のアナウンス
問い合わせ: 使い方や挙動に関する質問・トラブルシューティングの相談が寄せられます。問い合わせの内容は、UI の改善や FAQ の整備に活かされます。

要望: 利用者から「こうしてほしい」という要望が直接届きます。要望をそのまま実装するのではなく、「なぜそれが必要なのか」を掘り下げて本質的な課題を明確にすることを大切にしています。この対話を起点に機能改善が生まれることも多くあります。

機能追加・改善のアナウンス: 新機能をリリースした際に、チャンネルで周知します。利用者に実際に使ってもらう機会を作ることで、次のフィードバックにつながります。

定期的なサーベイと要望の収集
Slack チャンネルでは日常的にフィードバックが集まりますが、声を上げにくい利用者の意見も拾うために、定期的にサーベイを実施しています。満足度の定量評価に加えて、自由記述で具体的な要望や困りごとを集めています。

サーベイの回答からは、Slack では出てこなかった意見が見つかることもあります。
まとめ
本記事では、内製 Feature toggles 基盤 Darklaunch v2 の機能群と改善の進め方について紹介しました。
- リリース済みキーの Slack リマインド: 放置されたキーを定期的に検出・通知し、技術的負債の蓄積を防止
- リクエスト数と最後にリクエストされた日時: Datadog メトリクスを活用し、キーの削除判断を支援
- Owner team フィルタリング: 自チームのキーに素早くアクセスできる
- Fail-safe 機能: エラー時に false を返す安全設計で、基盤の障害がサービス全体に波及することを防止
- テスト stub ライブラリ: 管理画面の設定と同じ概念でテストを書ける
これらの機能は、Slack サポートチャンネルやサーベイを通じた利用者からのフィードバックを起点に改善を続けています。社内基盤は、作ったら終わりではなく、利用者との対話を通じて継続的に改善していくことが重要です。Darklaunch v2 は、開発者が安心してリリースできる体験を提供し続けるために、今後も改善を続けていきます。