頑張って追いつくAgent Week : Flagship

に公開

今北産業

  • Cloudflare上で遅延ゼロで動く、超高速な機能出し分けサービス「Flagship」
  • ユーザー属性やパーセント指定で、新機能のON/OFFをコード再デプロイなしでダッシュボードから一瞬で切り替え可能
  • いつでも安全にテストや段階的リリース(カナリアリリース)ができる。

何ができる?

要は : 機能の出し分けができる
内部実装はDO+KVらしい。

具体的にできること

  1. エッジ環境での「遅延ゼロ」の機能評価・ルーティング
  • Workers内部やHonoなどでAPIを構築している場合、env.FLAGSを使うことで、外部通信なしで即座にフラグを評価。
  • リクエストの処理経路の瞬時切り替え。
  • 例えば、移行テスト時や、新アルゴリズムの検証時などに、ユーザーの体感速度を落とさずにバックエンドのロジックを分岐。
  1. コンテキスト(ユーザー属性)に基づいた柔軟な出し分け
  • フラグをただON/OFFするだけでなく、リクエストに含まれる様々な情報(ユーザーID、契約プラン、アクセス元の国、メールアドレスなど)を組み合わせてルール化できます。
  • 「特定の管理者やスタッフ権限を持つユーザーにだけデバッグ用のUIを表示する」「特定のドメインからのアクセスにだけ先行機能を解放する」など、属性ベースのアクセス制御や機能提供を、コードを書き換えることなくダッシュボードから変更ができる。
  1. 段階的公開(パーセンテージロールアウト)
  • 新機能をいきなり全員に公開するのではなく、「まずは5%のユーザーから」といったような公開ができる。
  • 例えばモバイルやWebフロントで新UIをテストする際、Sticky bucketing(固定割り当て)により、ユーザーIDをベースに同じユーザーには常に同じ状態(ONならずっとON)を提供。
  1. JSONオブジェクトや数値/文字列の動的配信
  • フラグの戻り値は、単純な真偽値(Boolean)だけでなく、文字列、数値、JSONオブジェクトも扱えます。また、TypeScript環境では型安全に値を取得可能(getBooleanValue、getObjectValueなど)。
  • 例えばテーマカラーの設定値、APIのレートリミットの上限、UIのレイアウト構成データなどをJSONで持たせておくことで、アプリ自体のアップデートやデプロイを介さずに、サーバー側から動的に変更ができるように。
  1. 「OpenFeature」対応
  • Cloudflareにロックインせず、フィーチャーフラグの業界標準規格である「OpenFeature」を採用。
  • もし将来的にFlagship以外のプロバイダー(LaunchDarklyなど)に移行したくなった場合でも、アプリケーション側の評価ロジックを大幅に書き換える必要がない。

うれしそうなこと

  • Flagshipを読むWorkerを作成し、Service Bindingで連携させればWorkerごとに変更ができそう。
  • なんならDynamic Workerと繋げたらもっと面白そう
  • OpenFeature クライアントサイドSDKを使うことで直接取りに行くこともできるので、ボタンの表示・非表示などもこれで処理できる..?これは嬉しい。
  • なんならServerside-SDKもあるそうなので、使うためにWorkers必須というわけでもないらしい。

書き方

サーバーサイド

export default {
  async fetch(request, env) {
    // 1. フラグの評価(コンテキストを渡して即判定)
    const isNewUI = await env.FLAGS.getBooleanValue('new-ui', false, { 
      userId: 'user-123' 
    });

    // 2. 処理の分岐
    if (isNewUI) {
      return new Response("新機能のデータを返す");
    } else {
      return new Response("従来のデータを返す");
    }
  }
}

クライアントサイド

import { OpenFeature } from '@openfeature/web-sdk';

// 1. 初期化(アプリ起動時に1度だけ実行し、フラグ一覧を取得)
await OpenFeature.setProviderAndWait(new FlagshipClientProvider({ ... }));
const client = OpenFeature.getClient();

// 2. 必要な画面でフラグの評価
function MyPage() {
  const isNewUI = client.getBooleanValue('new-ui', false);

  // 3. 画面の出し分け
  if (isNewUI) {
    return <NewDesignButton />
  } else {
    return <OldDesignButton />
  }
}
会津大学学園祭実行委員会 テックブログ

Discussion