仕組みから学ぶ Web
応用読了目安 14#フィーチャーフラグ#段階的リリース#デプロイ#技術的負債

フィーチャーフラグ — 消し忘れたスイッチが、本番を壊す

使われていないフラグの名前を再利用したら、デプロイに失敗していた1台だけが3年前のコードを動かした。フラグはデプロイと公開を分ける道具で、分けたぶんだけ本番の状態の数が増える。

この記事の進み方

What — デプロイと公開を分ける

フィーチャーフラグは、コードの中の分岐を、デプロイせずに外から切り替えられるようにする仕組みです。

if (flags.isEnabled("member_rank_discount", user)) {
  price = applyRankDiscount(price, user);
}

これで、2つの操作を分けられます。

  • デプロイ — 新しいコードを本番に置く。フラグは OFF なので、利用者には何も変わらない
  • 公開 — フラグを ON にする。コードは変わらず、利用者に機能が見える

分けることで、公開を少しずつ行えます。社内だけ、1%だけ、特定の地域だけ。問題があれば、デプロイし直さずにフラグを切るだけで戻せます

Figureリリース用のフラグの一生
OFF でデプロイ準備

コードは本番にあるが、誰にも見えない

社内だけ ON確認

開発者と社内の利用者だけが新しい機能を使う

一部に公開公開中

利用者の 1% → 10% → 50% と広げる

全員に ON公開済み

すべての利用者が新しい機能を使う

コードから削除完了

分岐と古い経路を消し、フラグ自体も消す

1/5
OFF でデプロイ社内の利用者を対象に ON社内だけ ON本番のデータと本番の負荷で、まず自分たちが使う。検証環境では出ない問題がここで見つかる。

リリース用のフラグは、公開が終わったら消すまでが仕事。全員に公開したあと放置すると、使われない分岐と、使われない名前が残る。冒頭の事故はそこから始まった。

フィーチャーフラグ
コードの分岐を、デプロイせずに外から切り替える仕組み。フィーチャートグルとも呼ぶ。
段階的リリース
新しい機能を、利用者の一部から順に広げて公開すること。
キルスイッチ
問題が起きたときに、機能をすぐ止めるためのフラグ。長く残す前提で作る。
割り当ての固定
同じ利用者には、判定のたびに同じ結果を返すこと。利用者 ID から計算する。

フラグは、目的によって寿命が違う

「フラグ」とひとまとめにされがちですが、目的が違えば、いつ消すべきかがまったく違います

Compareフラグの種類

公開を段階的に行うため。全員に公開したら消す

new_checkout_flow
寿命
**数日〜数週間**
切り替える人
開発チーム
消すタイミング
全員に公開して安定したら
残すと
**使われない分岐と名前が残る**
注意
  • 作るときに削除の期限と担当者を決める
  • 100% にした日から、消すまでの時間を短くする
  • 冒頭の事故の `bulk_discount` は、これを3年残したもの

種類を区別せずに1つの仕組みで管理すると、消すべきフラグが残り、残すべきフラグが消される。作るときに種類と期限を決める。

確認 — ここまで読めたか

ON / OFF の2通りを取るフラグが、同じ画面の処理に3つあります。本番で起こりうるフラグの組み合わせは何通りですか?

まず選ぶ(解答例は a〜d の記号で説明します)

Why — なぜフラグが事故を生むのか

フラグの価値は、デプロイと公開を分けることでした。分けたということは、「本番にあるコード」と「本番で動いているコード」が一致しなくなったということです。

冒頭の事故は、この食い違いが3つ重なっています。

  • 消さなかった。 公開の終わった分岐が3年残り、名前が「使われていない」ように見えた
  • 名前を再利用した。 同じ名前が、コードの版によって別の意味を持った
  • デプロイの失敗に気づかなかった。 古い版の1台では、名前が古い意味のままだった

どれか1つでも無ければ、起きませんでした。

割り当ては、利用者で固定する

段階的に公開するとき、判定のたびにランダムに決めると、同じ利用者が画面を開くたびに新旧が入れ替わります。カートに入れたときは新しい画面、決済のときは古い画面、ということが起きます。

割り当ては利用者 ID から計算して固定します。

bucket = hash("new_checkout" + userId) % 100
bucket < 10 なら新しい画面(10% に公開)

同じ利用者は常に同じ側に入り、公開の割合を 10% から 50% に広げたときは、すでに新しい画面を見ていた 10% の人はそのままで、残りの一部が加わります。フラグの名前を式に含めるのは、別のフラグで同じ人ばかりが先行公開の対象にならないようにするためです。

確認 — ここまで読めたか

新しい決済画面を10%に公開するため、リクエストごとに乱数を引いて10%の確率で新しい画面を出しています。何が起きますか?

まず選ぶ(解答例は a〜d の記号で説明します)

演習 — まず自分で判断する

解説を読む前に、まず自分で判断してみてください。ここで一度詰まっておくと、 次の節の判断軸が「なるほど」ではなく「そう来たか」に変わります。

演習 — 設計判断を問う

新しい決済の流れを、フラグを使ってどう公開しますか?

与えられた条件
  • 決済の流れを作り直した。古い流れとは画面も API の呼び方も違う
  • EC サイトで、1日の注文は約2万件
  • 検証環境では確認したが、本番の決済サービスとの組み合わせは本番でしか確かめられない
  • フラグの管理はフラグ用のサービスで行い、アプリはそこから判定を取る
  • 過去に、公開後に消し忘れたフラグが数十個溜まっている
この軸で考える
  • · どの順で、何を見て、公開を広げるか
  • · 問題が起きたとき、何分で古い流れに戻せるか
  • · フラグの仕組みが落ちたとき、利用者は新旧どちらを見るか
まず選ぶ(解答例は a〜d の記号で説明します)

演習 — 説明できるか

「公開が終わったフラグは、そのまま残しておいても害は無いのでは」と言うプロダクトマネージャーに、消す理由を説明してください

与えられた条件
  • 相手はフラグで段階的に公開できることを気に入っている
  • 消す作業には、開発の時間が少し要る
  • 次の機能開発を急ぎたいと考えている

読み終わりましたか?

読了にすると、これを前提とする記事がロードマップで開放されます。