ããã«ã¡ã¯ãPlatform Team ã® tobi (@iam__tobi) ã§ãã
æ¬è¨äºã§ã¯ feature flag ã®åºç¤çäºé ã®èª¬æã¨ãPlatform Team ã§éçºãã¦ãã newmo ç¬èªã® feature flag åºç¤ã®è¨è¨ææ³ã¨å ¨è²ã«ã¤ãã¦äºæ®µæ§æã§ãç´¹ä»ãã¾ãã
ãããã feature flag ãå°å ¥ãããã¨èãã¦ããæ¹ã«ã¨ã£ã¦åèã«ãªãã°å¹¸ãã§ãã
èæ¯ã»æ¦è¦
ã¹ã¿ã¼ãã¢ããã§ãã newmo ã§ã¯ãå¤åã«ä¿æã«è¿½å¾ããéçºãµã¤ã¯ã«ãé«éã«åããã¨ãäºæ¥æé·ã®éµã¨ãªãã¾ãããã®ããã«ã¯ããã¤ã§ããªãªã¼ã¹ã§ããç¶æ ããä¿ã¡ãæ©è½è¿½å ãç´ æ©ãæ¬çªç°å¢ã«å±ããéçºããã¼ãæ¬ ããã¾ããã ãã©ã³ã¯ãã¼ã¹éçº *1 ã¯ãåä¸ã®ã¡ã¤ã³ãã©ã³ãã¸å°ããªå¤æ´ãé«é »åº¦ã«ãã¼ã¸ãããã¨ã§ (CI/CD ãé©åã«æ§ç¯ããã¦ããå ´å)ãé«é »åº¦ãªãããã¤ãå®ç¾ã§ãã¾ããå®é newmo ã§ã¯ãã©ã³ã¯ãã¼ã¹éçºãæ¡ç¨ãã¦ãããæè¿ã§ã¯ 1 æ¥ãããå¹³å 100 åã»ã© main ã¸ãã©ã³ãããã¼ã¸ããããã®ãã³ã«éçºç°å¢ã¸ã³ã¼ãããããã¤ããã¦ãã¾ãã
ããããã®ç¶æ ã§ã¯ããããã¤ã¨æ©è½ãªãªã¼ã¹ãåæã«è¡ããããããå®é¨çãªæ©è½ãä¸å ·åãå³åº§ã«å ¨ã¦ã¼ã¶ã¼ã¸é²åºããä¿®æ£ããã¼ã«ããã¯ã®ãã³ã«åãããã¤ãå¿ è¦ã¨ãªããã大ããªè² æ ã¨ãªãã¾ãã ã¾ããé«éãªéçºãµã¤ã¯ã«ã®ãªãã§ãéçºç°å¢ã¨æ¬çªç°å¢ã®æ©è½å·®ç°ãåãªãç°å¢å¤æ°ãã³ã¼ããã¼ã¹ã®å·®åã ãã§å®ç¾ããã®ã¯ç¾å®çã§ã¯ããã¾ãããã¦ã¼ã¶ã¼å±æ§ãã¨ã«æ©è½ãåºãåãããã¨ãå°é£ã§ãã
ããã§ feature flag ãéè¦ãªå½¹å²ãæããã¾ããnewmo ã® Platform Team ã§ã¯ããã©ã³ã¯ãã¼ã¹éçºã®ã¹ãã¼ãã¨å®å ¨æ§ã両ç«ããããããé«ä¿¡é ¼ã»ä½ã³ã¹ãã»éçºè ãã¬ã³ããªã¼ãª feature flag åºç¤ãã¼ãããè¨è¨ã»å®è£ ãã¾ããã
feature flag å ¥é
feature flag ã«ã¤ãã¦ãããä¸åº¦ãããããã¦ããã¾ãããã
feature flag ã解説ãã¦ããå ¥éè¨äºã¯ããããããã¾ãããä»å㯠Pete Hogdson æ°ã®è¨äºãç¹ã«åèã«ããã¦ããã ãã¾ããã
æ¬è¨äºã§ã¯ãã®è¨äºãåæã«è©±ãé²ãã¦ããã¾ãã
feature flag ã®æ¦è¦
è¨äºã§ã¯ feature flag ãæ¬¡ã®ããã«èª¬æãã¦ãã¾ãã
Feature Toggles (often also referred to as Feature Flags) are a powerful technique, allowing teams to modify system behavior without changing code.
(ä¸ç¥)
âFeature Togglingâ is a set of patterns which can help a team to deliver new functionality to users rapidly but safely.
feature flag (feature toggle) ã¯ãã³ã¼ãã夿´ãããã¨ãªãã·ã¹ãã ã®æ¯ãèããå¤ããããä»çµã¿ã§ããããã«ããéçºè ã¯ãæ°æ©è½ãè¿ éãã¤å®å ¨ã«æä¾ã§ãã¾ãã
feature flag ãç¨ããã³ã¼ãã®ã¤ã¡ã¼ã¸ã示ãã¾ãã
func (s *Service) SomeFunc(ctx context.Context) error { if s.featureflag.Evaluate(ctx, "do-experiments-flag") { // do something experimental } else { // do something stable } }
do-experiments-flag 㯠feature flag ã®ååã§ãããå®é¨çæ©è½ã®ãªã³ã»ãªããå¶å¾¡ãã¾ããããã«ãããå®é¨çæ©è½ã®ãã¼ã«ã¢ã¦ããç°å¢ãã¨ã«åãæ¿ããããã¦ã¼ã¶ã¼ãã¨ã«è©ä¾¡çµæãå¤åããããã§ãã¾ãããã¨ãã°ãããã»ã°ã¡ã³ãã«ã¯ãã©ã°å¤ã¨ã㦠true ãè¿ãã¦å®é¨æ©è½ããªãªã¼ã¹ããå¥ã®ã»ã°ã¡ã³ãã«ã¯ false ãè¿ãã¦ãªãªã¼ã¹ããªããã¨ãã£ãå¶å¾¡ãå¯è½ã§ãã
ãã®ããã«ã¦ã¼ã¶ã¼ãã¨ã«å¤ã®è©ä¾¡ãå¶å¾¡ããææ³ã¯ Dynamic Evaluation *2 ã¨å¼ã°ããæ¬è¨äºã§ã以éé »åºãã¾ãã
feature flag ã®æ§æè¦ç´
ãfeature flag ãå°å ¥ãããã¨ä¸å£ã«è¨ã£ã¦ããå®éã«ã¯è¤æ°ã®ç´°ããªè¦ç´ ã精緻ã«çµã¿åããã£ã¦æ©è½ãã¦ãã¾ããããã§ã¯ãfeature flag é¢é£ã®ããã°è¨äºã§ããåãä¸ããããæ§æè¦ç´ ãç´¹ä»ãã¾ã *3ã
ã¾ãã以ä¸ã®ãããªã·ã³ãã«ãªã³ã¼ããæ³å®ãã¾ãã
if featureflag.IsActive("holiday-greeting") { fmt.Println("Happy holidays!") }

Toggle Point
Toggle Point ã¨ã¯ããã©ã°ãå¤å®ããã³ã¼ãä¸ã®âåå²ç¹âã§ããä¸è¨ã®ä¾ã§ã¯IsActive("holiday-greeting") ã該å½ããããã§ãã©ã°ã®å¤ã«å¿ãã¦å®è¡ãã¹ãåãæ¿ããã¾ãã
Toggle Router
Toggle Router ã¯ã夿°ã® Toggle Point ã«å¯¾ãã¦ä¸è²«ããè©ä¾¡çµæãæä¾ããåä¸ã®æ
å ±æº (single source of truth) ã§ããä¾ã§ã¯ featureflag.IsActive ããã©ã°åãåãåããToggle Configuration 㨠Toggle Context ãç¨ãã¦å
é¨ãã¸ãã¯ã«åºã¥ãã¦çå½å¤ãè¨ç®ããçµæãè¿ãã¦ãã¾ãããããã£ã¦ããã®é¢æ°ã Toggle Router ã®å½¹å²ãæããã¾ãã
Toggle Context
Toggle Context ã¯ãToggle Router ããã©ã°ãè©ä¾¡ããéã«èæ ®ããæèæ å ±ã§ããä¾ã§ã¯ãç¾å¨ã®æ¥ä»ããæèã«å½ããå¯è½æ§ãããã¾ãããã»ãã«ãã¦ã¼ã¶ã¼ IDã»ã¦ã¼ã¶ã¼å±æ§ã»åç §å URL ãªã©å¤å²ã«ãããããã¸ãã¹ãã¸ãã¯ã¨æ·±ãçµã³ã¤ãã¾ããOpenFeature ã§ã¯ evaluation context ããã®å½¹å²ãæ ãã¾ãã
Toggle Configuration
Toggle Configuration ã¯ãToggle Router ããã©ã°ãè©ä¾¡ããããã«åç §ãã å¤é¨è¨å® ã§ãããã¨ãã° flagd ã§ã¯ã以ä¸ã®ãã㪠JSON å®ç¾©ãå©ç¨ãã¾ããflagd ã®è©³ç´°ã¯å¾è¿°ãã¾ãããããã§ã¯ããã©ã°è©ä¾¡ã«å¿ è¦ãªãã¹ã¦ã®æ å ±ãæ ¼ç´ãããè¨å®ãã¡ã¤ã«ãã¨èªèãã¦ããã ããã°è¯ãã§ãã
{ "$schema": "https://flagd.dev/schema/v0/flags.json", "flags": { "new-welcome-banner": { "state": "ENABLED", "variants": { "on": true, "off": false }, "defaultVariant": "off", "targeting": { "if": [ { "ends_with": [{ "var": "email" }, "@example.com"] }, "on", "off" ] } } } }
feature flag ã®ç¨®é¡
è¨äºã§ã¯ feature flag ã dynamism 㨠longevity ã® 2⯠軸㧠4⯠種é¡ã«åé¡ãã¦ãã¾ãã

- dynamism
ãã©ã°è©ä¾¡ãã©ãã ãåçã (=å®è¡æã«ã©ã®ç¨åº¦å¤åããã) ã示ãã¾ãã軸ã®å·¦å´ã«è¡ãã»ã©å¤ã®å¤å㯠ãããã¤åä½ãå³å´ã«è¡ãã»ã©ããç´°ããç²åº¦ã® ãªã¯ã¨ã¹ãåä½ ã§å¤åããã¨ä¾ç¤ºããã¦ãã¾ãã - longevity
ãã©ã°ãã³ã¼ããã¼ã¹ã«ã©ãã ãé·ãåç¶ãããã示ãã¾ãã
feature flag ã¯ã³ã¼ããã¼ã¹ã®è¤éæ§ãé«ãããããã«ãã´ãªãã¨ã«ãªã¼ãã¼ã·ãããéç¨ããªã·ã¼ãæç¢ºã«ãããã¨ãéè¦ã§ãããã©ã°ãå®ç¾©ããé㯠dynamism 㨠longevity ã®ç¹æ§ãèæ ®ããé©åãªã«ãã´ãªã¸åé¡ãã¾ãããã
Release Toggles
| ã¦ã¼ã¹ã±ã¼ã¹ | éçºä¸ã®ä¸å®å
¨ã»æªãã¹ãã®æ©è½ããæ¬çªã«ãããã¤ãã¤ã¤ã¦ã¼ã¶ã¼ã«ã¯éå
¬éã«ããã ãã©ã³ã¯ãã¼ã¹éçºãæ¯æ´ãããæ©è½ã®ãªãªã¼ã¹ã¨ãããã¤ãåé¢ãããã¨ããç¶ç¶çããªããªã¼ã®ååãå®ç¾ã |
| dynamism | é常ã«éçãç¹å®ã®ãããã¤ã§ã¯å¸¸ã«åãè©ä¾¡çµæãè¿ãããå®ç¾©ãããã |
| longevity | ããçå½ (é常 1ã2 é±éç¨åº¦)ã |
Experiment Toggles
| ã¦ã¼ã¹ã±ã¼ã¹ | ã«ããªã¢ãªãªã¼ã¹ãA/B ãã¹ããå¤å¤éãã¹ãã®å®æ½ã ã¨ã³ãã¦ã¼ã¶ã¼ã cohort (ã»ã°ã¡ã³ã) ã«åããã»ã°ã¡ã³ããã¨ã«è©ä¾¡çµæãå¤ããã |
| dynamism | é常ã«åçããªã¯ã¨ã¹ããã¨ã«è©ä¾¡çµæãå¤åã |
| longevity | å®å®æ§ã®æ¤è¨¼ãçµ±è¨çã«ææãªçµæãå¾ãããã¾ã§åç¶ã |
Ops Toggles
| ã¦ã¼ã¹ã±ã¼ã¹ | ã·ã¹ãã éç¨ä¸ã«åä½ãå¶å¾¡ããã é«è² è·æã«éè¦åº¦ã®ä½ãæ©è½ãç¡å¹åãã Kill Switch ãªã©ã |
| dynamism | éçå¯ãããããã¤åä½ã»ã©éçã§ã¯ãªããããªã¯ã¨ã¹ãåä½ã»ã©åçã§ããªãã |
| longevity | æ°æ©è½ã®å®å®æ§ãããã©ã¼ãã³ã¹ã¸ã®å½±é¿ãææ¡ã§ããã¾ã§åç¶ãå ´åã«ãã£ã¦ã¯ç¡æéã«æ®ããã¨ãããã |
Permission Toggles
| ã¦ã¼ã¹ã±ã¼ã¹ | ã¦ã¼ã¶ã¼å±æ§ã«å¿ãã¦æ©è½ï¼ä½é¨ãå·®å¥åã ä¾ï¼ææã¦ã¼ã¶ã¼ã®ã¿ããã¬ãã¢ã æ©è½ããæå¹åãå é¨ã¦ã¼ã¶ã¼åãã«ãã¢ã«ãã¡æ©è½ããå ¬éã (Champagne Brunch) |
| dynamism | é常ã«åçããªã¯ã¨ã¹ããã¨ã«è©ä¾¡çµæãå¤åã |
| longevity | ãã¬ãã¢ã æ©è½ãªã©ã管çããå ´åãæ°å¹´åä½ã§ç¶æããããã¨ãããã |
è£è¶³
âChampagne Brunchâ ã¯å é¨ã¾ãã¯ãã¼ã¿ã¦ã¼ã¶ã¼åãã«æ°æ©è½ãå è¡å ¬éããææ³ã®ä¿ç§°ã§ããå¤§è¦æ¨¡ãµã¼ãã¹ã§åºãæ¡ç¨ããã¦ãã¾ãã
OpenFeature
featureâ¯flag ãµã¼ãã¹ã¯ãOSS ãã SaaS (ãããã â¯FFaaS) ã¾ã§å¤ç¨®å¤æ§ã«åå¨ãã¦ãã¾ããUnleashãFlagsmithãLaunchDarklyãSplit.io ãªã©ã鏿è¢ã«äºæ¬ ãã¾ãããããããåãããã¯ããæä¾ãã ç¬èª SDK ãã¢ããªã±ã¼ã·ã§ã³ã¸çµã¿è¾¼ããã³ã«ã次ã®ãããªèª²é¡ãçãã¾ãã
- ãã³ãã¼ããã¯ã¤ã³
ä¹ãæãæã«ã³ã¼ããå ¨é¢æ¹ä¿®ããã³ã¹ããçºçãã - ãªãã¶ã¼ãããªãã£ã®ã°ãã¤ã
SDK ãã¨ã«ãã¬ã¡ããªãã¼ã«ã¨ã®çµ±åæ¹æ³ãç°ãªã
ããããæçåãè§£æ¶ããã¹ãèªçããã®ã OpenFeature ã§ãã

âOpenFeature is an open specification that provides a vendorâagnostic, communityâdriven API for feature flagging that works with your favorite feature flag management tool or inâhouse solution.â
OpenFeature ã¯ããã³ãã¼ãã¥ã¼ãã©ã«ãªå
±é API/SDK ã 10⯠以ä¸ã®è¨èªã§æä¾ãã¦ãã¾ããã¢ããªã±ã¼ã·ã§ã³å´ã¯ client.BooleanValue("some-flag") ã®ããã«çµ±ä¸çãªå¼ã³åºããæ¸ãã ãã§ãããå®éã®ãã©ã°è©ä¾¡ãã¸ãã¯ã¯ Provider ãã©ã°ã¤ã³ (flagdã»LaunchDarklyã»Flipt ãªã©) ãå·®ãæ¿ããã ãã§å¤æ´ã§ãã¾ãã主è¦ãããã¯ãã¯å¤è¨èªã§ Provider ãæä¾ããã¦ãã¾ãã â¯*4ã
ããã«ãããæ¬¡ã®ãããªå©ç¹ãå¾ããã¾ãã
- ããã¯ã¨ã³ããåãæ¿ãã¦ãã¢ããªæ¹ä¿®ã¯æå°é
- Hooks æ©æ§ã§ OpenTelemetry ãªã©æ¨ªæçå¦çã䏿¬æ³¨å ¥
- èªåå®è£ ãããã«ããã¼ã¸ã SaaS ã¾ã§ åã SDK ã§éç¨å¯è½
feature flag ãåãªããã¼ã«ã§ã¯ãªã ã¤ã³ã¿ã¼ãã§ã¼ã¹ ã¨ãã¦æãããã¨ã§ãå°æ¥ã®ç§»è¡ã»çµ±åã»å¤è¨èªéçºã«ãå¼·ãåºç¤ãç¯ããç¹ãæå¤§ã®é åã§ãã
2025⯠年 â¯7⯠æ â¯20⯠æ¥ç¾å¨ãOpenFeature 㯠CNCF ã® Incubating Project ã§ã â¯*5ã
flagd
newmo ã§ã¯ feature flag ã®è©ä¾¡ã¨ã³ã¸ã³ã¨ã㦠flagd ãæ¡ç¨ãã¦ãã¾ãã
flagd is a feature flag evaluation engine. Think of it as a ready-made, open source, OpenFeature-compliant feature flag backend system.
flagd 㯠OpenFeature æºæ ã®ã¤ã³ã¿ã¼ãã§ã¼ã¹ãå®è£ ãã¦ãããå ¬å¼ã« Provider ãæä¾ããã¦ãããããæåã«å©ç¨ãã OSS ã¨ãã¦éå¸¸ã«æåãªé¸æè¢ã§ãã
flagd ã®è©ä¾¡ã¢ã¼ãã«ã¯ RPC Evaluation 㨠In-Process Evaluation ã® 2 種é¡ãããã¾ãã
RPC Evaluation ã¯ãå¤é¨ããã»ã¹ã gRPC ãä»ã㦠flagd ããã»ã¹ã«ãã©ã°è©ä¾¡ã®ãªã¯ã¨ã¹ããè¡ãæ¹å¼ã§ãã䏿¹ãIn-Process Evaluation ã§ã¯ flagd ã®è©ä¾¡ã¨ã³ã¸ã³ãåä¸ããã»ã¹å
ã® goroutine ã¨ãã¦åãããããRPC Evaluation ã«æ¯ã¹ã¦ä½ã¬ã¤ãã³ã·ãå®ç¾ã§ãã¾ããnewmo ã§ã¯ Modular Monolith ãæ¡ç¨ãã¦ãããã¨ãããIn-Process Evaluation Mode ã鏿ããã®ãåççã ã¨å¤æãã¾ããã
ã¾ãããSaaS ã使ããèªç¤¾ç°å¢ã§ feature flag ãéç¨ãããã ã¨ãããã¼ãºã«å¯¾ãã¦ããflagd ã¯åªãã OSS ã®åè£ã¨ãªãã¾ããçç±ã¯ä»¥ä¸ã®ã¨ããã§ãã
- flagd ã¯ç¬èªã¹ãã¼ãã® JSON ã Toggle Configuration ã¨ãã¦æ¡ç¨ãã¦ãããå°ç¨ UI ãæããªããã å®å ¨ãª SSoT (Single Source of Truth) ãæ§ç¯ããããã
- è©ä¾¡ã¨ã³ã¸ã³ãã¼ãããä½ãã®ã¯å¤§ããªå´åãè¦ãã¾ãããflagd ã使ãã°æ¢åã®ä»çµã¿ãæµç¨ãã¤ã¤ãã¨ã³ã¸ã³é¨åã®å®è£ ç¥èã¯ä¸è¦ã§éç¨ãéå§ã§ãããããfeature flag ãèªç¤¾ç¨ã«ã«ã¹ã¿ãã¤ãºãããããè©ä¾¡ã¨ã³ã¸ã³ããã«ã¹ã¯ã©ããã§éçºããã®ã¯é¿ãããã ã¨ããã±ã¼ã¹ã§ç¹ã«é©ãã¦ããã
flagd ã® Toggle Configuration ã«ã¤ãã¦ã¯ å ¬å¼ããã¥ã¡ã³ã ã«è©³ç´°ãããã¾ããã以ä¸ã«ä¾ã示ãã¾ãã
{ "$schema": "https://flagd.dev/schema/v0/flags.json", "flags": { "new-welcome-banner": { "state": "ENABLED", "variants": { "on": true, "off": false }, "defaultVariant": "off", "targeting": { "if": [ { "ends_with": [{ "var": "email" }, "@example.com"] }, "on", "off" ] } } } }
flagd ã® Toggle Configuration ã¯å¤§ãã以ä¸ã®è¦ç´ ã§æ§æããã¾ãã
- state
- ãã©ã°ãæå¹ãã©ããã示ãã¾ã (true / false ã®å¤ãã®ãã®ã§ã¯ãªããå©ç¨å¯è½ãå¦ãã®ç¶æ )ã
- variants
- åãããå¤ (ããªã¢ã³ã) ã¨ãã¼ã®ãããã³ã°ã
- defaultVariant
- ã¨ã©ã¼çºçæã«ãã©ã¼ã«ããã¯ããããã©ã«ãå¤ã
- é常㯠false ã "stable" ãªã©ãå®å ¨ãªå¤ãè¨å®ãã¦ããã®ãæã¾ãã (誤ã£ã¦æ©è½ããªãªã¼ã¹ãããã®ãé²ããã)ã
- targeting
- evaluation context ã®æ å ±ã¨çµã¿åããã¦ã誰ã«ã©ã®å¤ãè¿ãããæ±ºå®ããã«ã¼ã«ãJsonLogic ã§è¨è¿°ããã
- ä¸è¨ä¾ã§ã¯ãevaluation context ã® email ã @example.com ã§çµããå ´å㯠trueãããã§ãªããã° false ãè©ä¾¡ããã«ã¼ã«ã
ãã®ããã« flagd ã®ã·ã³ãã«ãªæ§æã¯ã«ã¹ã¿ãã¤ãºæ§ã¨éç¨ã®å®¹æãã両ç«ããã¦ãããnewmo ã®æ¢åã® Platform ã¨ãé常ã«ç¸æ§ãè¯ãã§ãã
ãã©ã°è©ä¾¡ã®æµã
ããã¾ã§æ½è±¡çãªèª¬æãç¶ããã®ã§ãå®éã« featureâ¯flag ãã©ã®ããã« è¨å® â å¼ã³åºã â è©ä¾¡ ãããã®ãããOpenFeatureâ¯+â¯flagd ã®æ§æãä¾ã«ãããããã¾ãã

ã¾ã Toggle Point ã§ãOpenFeature Client ã®ã¤ã³ã¿ã¼ãã§ã¼ã¹ã§ãã©ã°ã®å¤ã®è©ä¾¡ã試ã¿ã¾ããã¾ããã®æãbeta_user=true ã¨ãã evaluation context (Toggle Context) ãåæã«ä¸ãã¦ãã¾ãã
次㫠Toggle Router ãå¼ã³åºããã¾ããToggle Router ã®ä¸ã§ã¯ flagd ã常ã«åãã¦ãããflagd ã¯
- å¤é¨ã½ã¼ã¹ã宿çã«ç¢ºèªãã¦å¸¸ã«ææ°ã® Toggle Configuration ãã¡ã¢ãªã«ãã¼ããã¦ãã
- ãªã¯ã¨ã¹ããåãããã¡ã¢ãªã® Toggle Configuration ã¨ãªã¯ã¨ã¹ãå 容 (ãã©ã°åãToggle Context) ããå¤ãè©ä¾¡ããçµæãè¿ã
ã¨ãããµã¤ã¯ã«ãç¶ãã¦ãã¾ãã
Toggle Configuration ã¯ãflagd ã®ãã®ãä¾ã«åºãã¦ãã¾ããtargeting ã®æå³ã¯ããæ¸¡ããã evaluation context ã« beta_user ã®ãã¼ããããå¤ã true ã§ãããªãã°ãã©ã°çµæã¨ã㦠trueã ããã§ãªããªãã° falseãã§ãã
Toggle Configuration ã®ä¿åå ´æã¯ãS3ãGCSãã³ã³ããå ã®ãã¼ã«ã«ãã¡ã¤ã«ã·ã¹ãã ãgRPC çµç±ãªã©ãã¾ãã¾ç¨æããã¦ãã¾ããFFaaS ã 㨠å°ç¨ UI ãã Toggle Configuration ãè¨å®ãã¦å®éã«ã¯ã¯ã©ã¦ãã«ä¿åããã¦ããã§ãããã
flagd ãåæã«ãããããã¾ããããä»ã® OSS ã FFaas ã§ã
- Toggle Router ã®ãªãã§åãã¦ããè©ä¾¡ã¨ã³ã¸ã³ã OpenFeature Provider ã OSS/FFaaS ã«ä¾å
- Toggle Configuration ã®ã¹ãã¼ããè¨å®ã®ä»æ¹ãä¿åå ´æ
ããç°ãªãã¾ããããã¾ããªãã©ã°è©ä¾¡ã®æµãã¯åãã§ãã
ãã¦ããã¾ã§ãè¸ã¾ããã¨ãä»åã®ãªã¯ã¨ã¹ãã§ã¯ Toggle Context ã¨ã㦠beta_user=true ãæ¸¡ãã¦ããã®ã§ true ãè©ä¾¡ããã¦è¿ã£ã¦ãããã¨ãçè§£ã§ãã¾ãã
feature flag å°å ¥ã®æè¡çè² åµ
feature flag ã¯æ±ºãã¦éã®å¼¾ä¸¸ã§ã¯ããã¾ãããããã æè¡çè² åµãçã¿åºãããã ãã¨ããæ¬ ç¹ã¨ãã¦é »ç¹ã«ææããã¾ãã代表çãªåé¡ã¯æ¬¡ã®ã¨ããã§ãã
Zombie Flags
å½¹ç®ãçµãããã©ã°ãã³ã¼ãã«æ®ããæ¡ä»¶åå²ãè¥å¤§åããåé¡ã§ãã誰ãã»ãã¤å®è£ ãããå±¥æ´ãææ§ã ã¨ãããããåé¤ãã¦ãããã©ã°ã夿ã§ãã¾ãããFlag Proliferation (ãã©ã°ã®å¢æ®)
ãã©ã°ãå¢ããããã¨ããã¹ãã±ã¼ã¹ãççºçã«å¢å ãããã¹ãã«ãã¬ãã¸ãä½ä¸ãã¾ããè¤æ°ãã©ã°ã®çµã¿åããã§ãã°ãæ½å¨åãããããªãç¹ãåä»ã§ãããã©ã°åä¸ä¸è´
ãã©ã°åã magic string ã¨ãã¦ç´æ¥ã³ã¼ãã«æ¸ãã¨ãOSSã»SaaS å´ã§è¨å®ãããã©ã°åã¨ã®ä¸ä¸è´ãèµ·ããããããªãã¾ãããã©ã°ãåå¨ããªã/ã¿ã¤ããã¹ã¨ãã£ãåç´ãã¹ããæå³ããªãåå²ãæããªã¹ã¯ãããã¾ãã
ãããã®è² åµã¯ feature flag èªä½ã®ä¾¡å¤ã大ããæãªãããã¾ãããfeature flag ã«ããè² åµãæãã¤ã¤ã¡ãªãããæå¤§åããããã«ã¯ãã¬ããã³ã¹ã¨ãªã¼ãã¡ã¼ã·ã§ã³ ãæ¬ ããã¾ããã
newmo ã® feature flag åºç¤
newmo feature flag ã®å©ç¹ãæå¤§éã«æ´»ããã¤ã¤æ¬ ç¹ãä»çµã¿ã§æãè¾¼ã¿ãä½ããã éçºè ã®çç£æ§åä¸ ãåªå ããåºç¤ãæ§ç¯ãã¾ãããæ¬ç« ã§ã¯ããã®è¨è¨ææ³ã¨åææ¡ä»¶ãæ¦è¦³ãã¾ãã
åæ
newmo ã§ã¯ããµã¼ãã¼ãµã¤ãå®è£ ã«ã¯ Modular Monolith ã¢ã¼ããã¯ãã£ãæ¡ç¨ãã¦ãã¾ããæ©è½ãã¨ã«åå²ãããåãµã¼ãã¹ã component ã¨å¼ã³ãç¸äºéä¿¡ã«ã¯ gRPC ãç¨ãã¾ãããã®è¨äºã§ component ã¨ããèªãç»å ´ããå ´åã¯ããModular Monolith ãæ§æãã 1⯠ã¢ã¸ã¥ã¼ã«ãã®æå³ã ã¨æãã¦ãã ããã*6
è¨è¨ææ³
ããã§ã¯ã次㮠4⯠ã¤ã®è¦³ç¹ãã newmo ã® featureâ¯flag åºç¤ã®è¨è¨ææ³ã説æãã¾ãã
1. èªç¥è² è·ã®è»½æ¸
Platformâ¯Engineering ã®æèã§é »åºãããéçºè ã®èªç¥è² è·ãããã«ä¸ããããã¨ãã課é¡ã«å¯¾ããnewmo ã§ã¯ã¨ã㫠宣è¨çå®ç¾©ã»èªåçæã»fireâ¯andâ¯forget ã® 3⯠ç¹ã«æ³¨ç®ãã¦è¨è¨ãã¾ããã
A. 宣è¨çå®ç¾©
featureâ¯flag ã®ç¬èªã¹ãã¼ãã Protocolâ¯Buffers ã§å®ç¾©ãããã®ã¹ãã¼ãã«å¾ã£ã¦ YAML ã§ãã©ã°ãè¨è¿°ãã¾ããéçºè
ã¯ç°¡æ½ã§æçãªã¤ã³ã¿ã¼ãã§ã¼ã¹ã§ Toggleâ¯Configuration ã宣è¨ã§ããGitHub ã® â¯main⯠ãã©ã³ãããå
¨ç°å¢ã§æå¹ãªãã©ã°ç¶æ
ãã® SSoT (Single Source of Truth) ã¨ãªãã¾ããéå»ã®è¨å®ã Configurationâ¯asâ¯Data ã¨ãã¦å®å
¨ã«ãã¼ã¸ã§ã³ç®¡çããã¦ãã¾ãã
B. èªåçæ
A ã«ãã£ã¦å®ç¾©ããã Toggle Configuration ãå
¥åã«ãå OSS/FFaaS åã Toggleâ¯Configuration 㨠Toggleâ¯Router ãèªåçæãã¾ããToggleâ¯Context ãæ±ãå
é¨ãã¸ãã¯ã¯ç»ä¸çã«å®è£
ã㦠Router ããåãé¢ããå component ç¨ã«ã¯èãã©ããã¼ã®ã¿ãèªåçæãããããå¼ã³åºãã ãã§ééçã« Dynamicâ¯Evaluation ãæ©è½ãã¾ããããã«ãã¹ãå°ç¨ã®ãªã³ã¡ã¢ãªã¹ãã¢ã¨ãã«ãã¼ãèªåçæãããã¹ãã±ã¼ã¹ãã¨ã«ä»»æã®å¤ã override ãããã¨ãå¯è½ã§ããããã«ãããã©ã°ã®åãå¾ãå¤ã¯ enum ã¨ãã¦åå®å
¨ã«æ±ãããã©ã°åã®ä¸ä¸è´ã¨ãã£ããã¥ã¼ãã³ã¨ã©ã¼ãåççã«æé¤ã§ãã¾ãã
A ã§ã¹ãã¼ããä¸å¯§ã«è¨è¨ãã¦ããã°ãToggle Configuration 㨠Toggle Router ã¯åççã«èªåçæã§ããã¯ãã§ãããªããªãå OSS, SaaS åãã® Toggle Configuration ã¯ç¬èªã¹ãã¼ãã® Toggle Configuration 表ç¾ã®é¨åéåã«ãªã£ã¦ãããToggle Router ã¯è¤éãªå é¨ãã¸ãã¯ãåãé¢ãã¨åã« Toggle Context ã¨ãã©ã°åã§åãåããã¦ããã©ã°è©ä¾¡çµæãè¿ã責åããè² ã£ã¦ããªãããã§ãã
C. fireâ¯andâ¯forget
Zombieâ¯Flag 対çã¨ãã¦ã¯ä¸è¬ã«ãexpiration date ã®ä»ä¸ããåé¤ãã±ããã®çºè¡ããSlack éç¥ããªã©ãææ¡ããã¾ãããéçºè
ã®èªç¥è² è·ãæãä½ãã®ã¯ããã©ã°ãå®ç¾©ããããä¸è¦ã«ãªã£ãã¨ãèªåã§æ¶ãããç¶æ
ã ã¨èãã¾ãããnewmo ã§ã¯ Toggleâ¯Point ããããã©ã°ã®åå¨è¨¼æã§ããã¨å®ç¾©ãã宿ã¸ã§ãã§ãã©ã°ãã¨ã® Toggleâ¯Point æ°ãè¨æ¸¬ãã¦åç
§ãããªããªã£ããã©ã°ãèªååé¤ãã¦ãã¾ãã
ããã㦠å®ç¾© â çæ â åé¤ ã¾ã§ã®ã©ã¤ããµã¤ã¯ã«ããã¹ã¦ç¬èªåºç¤ã§ä¸å 管çãã¦ãã¾ããåé ç®ã®è©³ç´°ã¯å¾è¿°ãã¾ãã
2. ä½ã³ã¹ã
ãã³ã¹ãã㯠component ã®ç®¡çã³ã¹ããééçã³ã¹ããæ°ããªãã©ã°ãå®ç¾©ããå¿ççã³ã¹ãã® 3⯠å´é¢ã§è©ä¾¡ãã¦ãã¾ãã
ã¾ã管çã³ã¹ãã«ã¤ãã¦ãnewmo ã§ã¯ã¯ã¼ã¯ãã¼ãã« Cloud Run ãæ¡ç¨ãã¦ãã¾ããããµã¼ãã¹ã 1⯠ã¤å¢ãããã¨ã«ç®¡ç対象ãå¢ããã®ã¯å¾çã§ã¯ããã¾ãããããã§ flagd ã® InâProcess Evaluation mode *7 ãå©ç¨ããModularâ¯Monolith å
ã§è©ä¾¡ã¨ã³ã¸ã³ãåããã¦ãã¾ããããã«ããå¤é¨ãµã¼ãã¹ãå¢ãããã«æ¸ã¿ãéç¨è² è·ã極å°åã§ãã¾ããã
ééçã³ã¹ãããflagd ããã¼ã¹ã«ããèªåå®è£
ã§ããããã©ã³ãã³ã°ã³ã¹ããåºæ¬çã«å°é¡ã«æãããã¾ããåè¿°ã®ã¨ãã追å ã® Cloud Run ã¯ä¸è¦ãªã®ã§ã¤ã³ãã©è²»ç¨ãå¢ãã¾ããã
å¿ççã³ã¹ãã«ã¤ãã¦ã¯ãèªç¥è² è·åæ¸ã®æ½çã«ãã YAML ãã¡ã¤ã«ãä½æã»æ´æ°ã PR ãåºãã ãã§ãã©ã°ãå®ç¾©ã§ãããããUI æä½ãæåè¨å®ããªããéçºè ã¯è¿·ãããã©ã°ã追å ã§ãã¾ãã
3. æ¢åã®ä»çµã¿ã¨ã®çµ±å
newmo ã®ã¢ããªã±ã¼ã·ã§ã³ã«ãããèªè¨¼ã»èªå¯ã¯ Security Token Service Pattern ãç¨ãã¦ãã¾ããAPI Gateway ã¬ã¤ã¤ã§ã¦ã¼ã¶ã¼ã® Access Token ã Security Token Service ã«æ¸¡ããå
é¨ãã¼ã¯ã³ã¸å¤æããããã§ gRPC ãä»ãã¦å component ã«ä¼æããã¦ãã¾ãããã®å
é¨ãã¼ã¯ã³ã«ã¯ sub (ã¦ã¼ã¶ã¼ ID) ãåç¨®å±æ§ãå«ã¾ãããããfeature flag ã® Toggleâ¯Context ã¨ãã¦ãã®ã¾ã¾å©ç¨å¯è½ã§ããæ¢åèªè¨¼åºç¤ã«èªç¶ã«çµã¿è¾¼ããããéçºè
ã¯éåæãªã Toggleâ¯Configuration ãè¨è¿°ã§ãã¾ãã

4. é«ä¿¡é ¼æ§
feature flag åºç¤ã¯é«ãä¿¡é ¼æ§ãå¿
é ã§ããå¯ç¨æ§ãããã«ããã¯ã«ãªãã±ã¼ã¹ã¯ç¾å¨ããã¾ããããToggleâ¯Configuration ã®èªåçæã Toggleâ¯Context ã®ãã¸ãã¯ã«ãã°ãããã°å³ã¤ã³ã·ãã³ãã«ã¤ãªããã¾ãããã®ããèªåçæã³ã¼ã㯠Goldenâ¯Filesâ¯Test *8 ã§å·®åãæ¤åºããè©ä¾¡ãã¸ãã¯ã¯ fake-gcs-server ãç«ã¦ã¦å®éã«ã¨ã³ã¸ã³ãåããã夿§ãªæ¡ä»¶ã§ãã©ã°è©ä¾¡ãè¡ããã¨ã§å®ç°å¢ã«è¿ãå½¢ã§ãã¹ãã«ãã¬ãã¸ã確ä¿ãã¦ãã¾ããããã«è©ä¾¡ã¨ã³ã¸ã³ã® Metricsã»Traceã»Log 㯠OpenTelemetry Collector ãçµç±ã㦠Datadog ã¸éä¿¡ããéç¨é¢ã®å¯è¦³æ¸¬æ§ãæ
ä¿ãã¦ãã¾ãã*9
ãã®ä»ã«ãããã¥ã¡ã³ãæ´åãç¬èª OpenFeature Provider ã®éçºãå¤è¨èªã»å¤ããã»ã¹ã¸ã®å±éãªã©ãå°æ¥æ¡å¼µãè¦éã«å ¥ãã¦åºç¤ãé²åããã¦ãããä»å¾ãé«ãä¿¡é ¼æ§ãä¿ã¡ãªããæ©è½æ¡å ãå³ãäºå®ã§ãã
newmo ã«ããã feature flag ã®åé¡
newmo ã§ã¯ Pete Hodgson æ°ã® 4 åé¡ãåèã«ãã¤ã¤ããããã¯ãç¹æ§ã«åããã¦å®ç¾©ãåèãã¾ããã

大ããªç¸éç¹ã¯ä¸ã¤ããã¾ãã第ä¸ã« Release Toggles ã®ä½ç½®ã¥ããå³ (=ããåç) ã¸å¯ã£ã¦ãããã¨ã第äºã« Static Toggles ã¨ããæ°ããã«ãã´ãªãè¨ãããã¨ã第ä¸ã« Ops Toggles 㨠Permission Toggles ãç¾æç¹ã§ã¯å®ç¾©ãã¦ããªããã¨ã§ãã
Static Toggles ã¯ãµã¼ãã¼åæåæã® DI ãå¤é¨ãµã¼ãã¹ã®ãã¼ã¸ã§ã³åãæ¿ããªã©ãç°å¢å¤æ°ã«è¿ãç¨éã§ä½¿ããã©ã°ã§ãããã ãåãããã¤ãä¼´ããã«æ¯ãèããå¤ããããç¹ã大ããªéãã§ãæ°è¦ãµã¼ãã¹ã®å°å ¥æ¤è¨¼ãç°å¢ãã¨ã®ãµã¼ãã¹åãæ¿ããªã©ã«é©ãã¦ãã¾ãã
Release Toggles ã¯æ©è½ããªãªã¼ã¹ãããã©ããã true / false ã§å¤å®ãããã©ã°ã§ãHodgson æ°ã®å®ç¾©ã¨ç°ãªã ã¦ã¼ã¶ã¼æ å ±ã Toggle Context ã¨ãã¦æã¤ ãã¨ãåæã«ãã¦ãã¾ãããã®ããç°å¢å¥ã®ãã¼ã«ã¢ã¦ãå¶å¾¡ã«å ããå é¨ã¦ã¼ã¶ã¼éå®ã® QA ãªãªã¼ã¹ã®ãããªã¦ã¼ã¹ã±ã¼ã¹ã«ãæ´»ç¨ã§ãã¾ãã
Experiment Toggles ã¯ã¦ã¼ã¶ã¼ãè¤æ°ã®ã»ã°ã¡ã³ãã«åå²ããåã»ã°ã¡ã³ãã«å¯¾ãã¦ä»»æã®ãã¼ã»ã³ãã¼ã¸ã§ä»»æã®æååãè¿ããã©ã°ã§ããA/B/n ãã¹ããã«ããªã¢ãªãªã¼ã¹ãªã©ãããç´°ããªå®é¨ã»æ¤è¨¼ã§å¹æãçºæ®ãã¾ãã
åå®ç¾©ã®èæ¯ã¨ãã¦ãnewmo ã§ã¯ãã©ã¤ãã¼åãã¢ããªãªã©ã¢ããªãã£é¢é£ãããã¯ããæä¾ãã¦ãã¾ããããªãªã¼ã¹ç±æ¥ã®ãã°ãé大ã¤ã³ã·ãã³ãã«ã¤ãªããã¾ãããã®ãããç¹å®ã¦ã¼ã¶ã¼ã ããå®å ¨ã«å¯¾è±¡åãããã¨ããè¦ä»¶ãå¤ããRelease Toggle ã® dynamisim ãä¸ãã¦ã¦ã¼ã¶ã¼å±æ§ãèæ ®ã§ããããã«ãã¦ãã¾ãã
ã¾ã Experiment Toggle ã許容ãã dynamism 㯠Release Toggle ã® superset ã§ããããã2 ã«ãã´ãªã®ã¬ã³ã¸ãä¸é¨éãªãããå³ç¤ºãã¦ãã¾ããéçºè 㯠A/B/n ãã¹ããã«ããªã¢ãªãªã¼ã¹ãããå ´åãåç¶æéãé·ãã¨äºæ³ãããå ´åã«ã¯ Experiment Toggle ããããã§ãªãå ´å㯠Release Toggle ãå©ç¨ãã¾ããå³ã¯ Pete Hodgson æ°ã®ãªãªã¸ãã«å³ã®ä¸ä½é åãæ¡å¼µããã¤ã¡ã¼ã¸ã§ãç¾ç¶ã¦ã¼ã¹ã±ã¼ã¹ã®ãªã Ops Toggle 㨠Permission Toggle ã¯å®ç¾©ãã¦ãã¾ããããå°æ¥çã«å¿ è¦ã«ãªãã°ä¸æ¹åã¸é åãæ¡å¼µããæ³å®ã§ãã
ã¢ã¼ããã¯ãã£

ä¸å³ã newmo ã«ããã feature flag åºç¤ã®å ¨ä½åã§ãã
ã¾ã Toggleâ¯Configuration 㯠flagd ã® JSONâ¯Schema ã«å¾ã JSON å½¢å¼ã§ããããã«ã¯ã宣è¨çå®ç¾©ãã®ã»ã¯ã·ã§ã³ã§è¿°ã¹ã newmo ç¬èªã¹ãã¼ãã flagd ã¹ãã¼ãã¸å¤æããçµæãæ ¼ç´ããã¾ãã
次㫠OpenFeature Provider Layer ã§ããflagd ã® In-Process Resolver (In-Process Evaluation Mode) ã«ã¯ãToggleâ¯Configuration ããã¼ãªã³ã°ãã¦ã¡ã¢ãªã«ä¿æãã sync provider ã¨ããå é¨ã³ã³ãã¼ãã³ããåå¨ãã¾ããå ¬å¼ã«ãããã¤ãå®è£ ãæä¾ããã¦ãã¾ãããnewmo ã® Modularâ¯Monolith ã§ã¯ 1⯠ã¤ã® syncâ¯provider ãè¤æ°ã® GCS⯠ãã±ããã宿çã«ç£è¦ããå¿ è¦ããããããèªåã§ syncâ¯provider ãå®è£ ãã¾ãããflagd ç¨ã® OpenFeatureâ¯Provider èªä½ã¯æ¢ã« OSS ã¨ãã¦å ¬éããã¦ãããããIn-Process Evaluation Mode ã§èµ·åãã¤ã¤èªä½ syncâ¯provider ã DI ããã ãã§ç°¡åã« Provider ãæ§æã§ãã¾ãã
OpenFeature Client Layer ã§ã¯ãfeatureâ¯flag ã®ã«ãã´ãªå¤å®ã«å¿ããå¦çãå
é¨ãã¼ã¯ã³ãã Evaluationâ¯Context (Toggleâ¯Context) ãçæããå¦çãOpenFeatureâ¯Client ã®ã©ããã«ãã BooleanValue/StringValue ã§å¤åå¾ãããã« Trace/Metrics/Log ã Datadog ã¸éä¿¡ããå¦çãæ
ãã¾ãã
Toggle Router Layer ã¯ãèªåçæãã®ã»ã¯ã·ã§ã³ã§è©³è¿°ããããã«ãç¬èª Toggleâ¯Configuration ããèªåçæãããèãã©ããã¼ã§ããå é¨çã«ã¯åè¿°ã® OpenFeature Client Layer ã®ã¡ã½ãããå¼ã³åºãã ãã®ã·ã³ãã«ãªæ§é ã«ãªã£ã¦ãã¾ãã
Toggle Point Layer ã¯å component ã®åæåããã¸ãã¹ãã¸ãã¯ãè¨è¿°ãããå ´æã§ãæ°æ©è½ã®ãªãªã¼ã¹ãã«ããªã¢ãªãªã¼ã¹ãè¡ãããç®æã« Toggleâ¯Point ãæ¿å ¥ãã¾ãã
mobile / web ãªã©ã¯ã©ã¤ã¢ã³ããµã¤ãããããã¯å¥ããã»ã¹ãã featureâ¯flag ãåç
§ãããå ´åããåãåºç¤ã«ã¢ã¯ã»ã¹ãã¾ããOpenFeature Client Layer ãèãã©ãããã featureflag component ããã®è²¬åãæ
ããGraphQL ã gRPC çµç±ã§ãã©ã°è©ä¾¡ãæä¾ãã¾ããåè¨èªãã¨ã«ç¬èªã® OpenFeatureâ¯Provider ãç¨æããåæ§ã«èªåçæããã Toggleâ¯Router ãçµã¿è¾¼ãã§ãããããããã§èª¬æããæ§é ãããããã®ã©ã³ã¿ã¤ã ã«å
å
ããã¾ãã
宣è¨çå®ç¾©
newmo ã§ã¯ã¢ãã¬ããæ¡ç¨ãã¦ãããmobile/web/server/IaC ãªã©ããã¹ã¦ã®ã½ã¼ã¹ã³ã¼ãã Git ã§ä¸å 管çãã¦ãã¾ããfeature flag ã«ã¤ãã¦ãåãææ³ãé©ç¨ãããGit ãè¦ãã°ç¾å¨ãã¹ã¦ã®ç°å¢ã® Toggle Configuration ãææ¡ã§ãããç¶æ ãç®æãã¾ããããã®ãã Toggle Configuration 㯠YAML ã§å®£è¨ããã½ã¼ã¹ã³ã¼ãã¨ã¨ãã«ãã¼ã¸ã§ã³ç®¡çãã¦ãã¾ãã
featureflags: - name: "some-feature" release: targeting: preset: FEATURE_FLAG_TARGET_PRESET_ALL_END_USER variant: local: true dev: true stg: true prod: false
ä¸è¨ã¯ some-feature ã¨ãã Release Toggles ãå®ç¾©ããä¾ã§ããtargeting.preset ã¯è©ä¾¡å¯¾è±¡ã示ãããªã»ããã§ãFEATURE_FLAG_TARGET_PRESET_ALL_END_USER ã¯ããã¹ã¦ã®ã¨ã³ãã¦ã¼ã¶ã¼ãã表ãã¾ãããã®ã»ãã«ããå
é¨ã¦ã¼ã¶ã¼ã®ã¿ããç°å¢ãã¨ã«æå® ID ã®ã¦ã¼ã¶ã¼ããç¹å®å±æ§ãæã¤ã¦ã¼ã¶ã¼ããªã©ããã¾ãã¾ãªããªã»ãããç¨æãã¦ãããå¿
è¦ã«å¿ãã¦èªç±ã«æ¡å¼µã§ãã¾ãã
variant ã»ã¯ã·ã§ã³ã§ã¯ç°å¢ãã¨ã®è©ä¾¡çµæã宣è¨ã§ãã¾ããä¾ã§ã¯ ãã¼ã«ã«ã»éçºã»ã¹ãã¼ã¸ã³ã°ç°å¢ ã§ã¯å¸¸ã« trueãæ¬çªç°å¢ ã§ã¯ false ãè¿ãããè¨å®ãã¦ãã¾ããã³ã¼ãã夿´ãã YAML ãæ´æ°ããã ãã§ãã¼ã«ã¢ã¦ãæ¦ç¥ãåãæ¿ãããããããã¬ãã¥ã¼ããã¼ã«ããã¯ã®éç¨ã³ã¹ããæå°åã§ãã¾ãã
ãªã Static Toggles 㨠Experiment Toggles ãåæ§ã« Protocol Buffers ã§åå®å ¨ãªã¹ãã¼ããå®ç¾©ãã¦ãããéçºè 㯠YAML ã§ç´æçã«ãã©ã°ã追å ã»ç·¨éã§ãã¾ãã
èªåçæ
ä¸ã§å®ç¾©ãã Toggle Configuration ãå ã«ã
- flagd ã® Toggle Configuration
- åè¨èªåãã® Toggle Router
- åè¨èªåãã®ãã¹ããã«ãã¼
ãèªåçæãã¦ãã¾ãã
some-feature ãä¾ã«ããã¨ãflagd å´ã® Toggle Configuration ã¯æ¬¡ã®ããã«ãªãã¾ãã
{ "$schema": "https://flagd.dev/schema/v0/flags.json", "flags": { "<component name>.some-feature": { "state": "ENABLED", "variants": { "off": false, "on": true }, "defaultVariant": "off", "targeting": { "if": [ { "and": [true] }, "on", "off" ] }, "metadata": { "category": "release" } } } }
YAML ã§å®£è¨ããå
容ããã®ã¾ã¾ JSON ã«å¤æããã¦ãã¾ããtargeting ãè¦ãã¨ã常㫠"on" (=true)ãã¨è©ä¾¡ããããã¨ããããã¾ããtargeting.preset ã«è¤éãªããªã»ãããæå®ããå ´åã§ããJsonLogic ã¸èªåçã«å¤æãããããæè»ãªã«ã¼ã«çæãå¯è½ã§ãã
Go åãã® Toggle Router ã¯æ¬¡ã®ããã«èªåçæããã¾ãã
// Code generated by xxx; DO NOT EDIT.
package featureflag
import (
"context"
"github.com/newmo/.../featureflag"
)
const component = "<component name>"
type ReleaseToggle interface {
SomeFeature(ctx context.Context) bool
}
type releaseToggle struct {
client featureflag.Client
}
func NewReleaseToggle(client featureflag.Client) ReleaseToggle {
return &releaseToggle{client: client}
}
func (r *releaseToggle) SomeFeature(ctx context.Context) bool {
flagName := "<component name>.some-feature"
v, err := r.client.BooleanValue(ctx, flagName, false)
if err != nil {
return false
}
return v
}
ãã©ã°åã UpperCamelCase ã«ããã¡ã½ãããèªåçæãã¦ãã¾ãããã©ã°ãå¢ãã¦ãã¡ã½ãããå¢ããããããã©ã°åã® typo ãåççã«çºçãã¾ãããéçè§£æããããããå¾è¿°ãããã©ã°ä½¿ç¨åæ°ã®éè¨ã«ãå½¹ç«ã¡ã¾ããã¾ã Static Toggles ã Experiment Toggles ã®ããã«è©ä¾¡å¤ã string åã«ãªãå ´åããå®ç¾©ããã variant ä¸è¦§ ãã enum ãèªåçæãã¦åå®å
¨ã«æ±ãã¾ãã
ãã¹ããã«ãã¼ã¯ä»¥ä¸ã®ããã«çæããã¾ãã
// Code generated by xxx; DO NOT EDIT.
package featureflagtest
import (
"context"
"github.com/newmo/.../fakefeatureflag"
)
const component = "<component name>"
type FlagSetter struct {
client *fakefeatureflag.Client
}
func NewFlagSetter(client *fakefeatureflag.Client) *FlagSetter {
return &FlagSetter{client: client}
}
func (f *FlagSetter) SetSomeFeature(ctx context.Context, value any) error {
flagName := "<component name>.some-feature"
err := f.client.SetFlag(ctx, flagName, value)
if err != nil {
return err
}
return nil
}
fakefeatureflag ã¯ã¡ã¢ãªä¸ã«ãã©ã°å¤ãä¿æãããã§ã¤ã¯ã¯ã©ã¤ã¢ã³ãã§ãããã¹ãåã«ä»»æã®å¤ãã»ããã§ãããããåå²ãã¨ã®ã«ãã¬ãã¸ãé«ãããããªãã¾ãã
ãããã®ã³ã¼ã㯠Go ã ãã§ãªããfeature flag ãå©ç¨ããä»è¨èªåãã«ãåæ§ã«èªåçæããã¾ãã
fire and forget
âfire and forgetâ ã¨ã¯ãæ¬æ¥ã¯å¼ã³åºãå´ãéåæãªã¯ã¨ã¹ããéã£ããã¨ãã¬ã¹ãã³ã¹ãå¾ ããã«å¾ç¶å¦çãé²ããè¨è¨ãæãã¾ããnewmo ã® feature flag åºç¤ã§ãåãçºæ³ãæ¡ãããä¸åº¦å®ç¾©ãã¦å©ç¨ããããå½¹ç®ãçµãããã©ã°ã¯èªåã§æ¶ãã¦ããããç¶æ ãç®æ¨ã«ãã¦ãã¾ãã
éçºè
ã YAML ã§å®£è¨ãã Toggleâ¯Configuration ã¯ãmain ã¸ã®ãã¼ã¸ãããªã¬ã¼ã« GitHubâ¯Actions ãèªåã§ flagd ç¨ JSON ã«å¤æããGCS ã¸ã¢ãããã¼ããã¾ããéã« Toggleâ¯Point (ãã©ã°å¼ã³åºãç®æ) ã 0 ã«ãªã£ã feature flag 㯠CI ã«ãã£ã¦æ¤åºãããåãã CI ä¸ã§ã¯ãªã¼ã³ã¢ããããã¾ãã

ããã§æ³¨æãã¹ãã¯ãToggleâ¯Configuration ã®åæã¿ã¤ãã³ã°ã¨ Toggleâ¯Router ã®ãããã¤ã¿ã¤ãã³ã°ãå¿
ãããä¸è´ããªãç¹ã§ããConfiguration ã¯ãã¹ã¦ã®ç°å¢ã§ main ã¸ãã¼ã¸ãããç¬éã«åæ ããã¾ãããRouter (=ã¢ããªã±ã¼ã·ã§ã³ã®ãããã¤) ã¯ç°å¢ãã¨ã«ã¿ã¤ã ã©ã°ãçããå¯è½æ§ãããã¾ã (ä¾ãã°ããªãªã¼ã¹ãããã©ã³ããåç°å¢ã§ç°ãªãéç¨ãªã©)ããããã£ã¦ çã«åé¤ãã¦ãããã©ã° ã¯ããåç°å¢ã§ç¨¼åãã¦ãããã¹ã¦ã®ãã¼ã¸ã§ã³ã®ã½ã¼ã¹ã³ã¼ãã§ Toggleâ¯Point ã 0 ã«ãªã£ãå ´åãã«éããã¾ãã

ãã®ãããã®è©³ç´°ã¯ãå¼ç¤¾ Iwamin (@B_Sardine) ããã«ããçºè¡¨è³æã詳ããã®ã§ãã²åç §ãã¦ãã ãã â¯*10ã
Toggleâ¯Point ã®æ¤åºã¯æ¬¡ã®æ¹æ³ã§å®è£ ãã¦ãã¾ããGo ã³ã¼ã㯠AST ãç¨ããéçè§£æã§ç¢ºå®ã«å¼ã³åºããæããã»ãã®è¨èªã¯æ«å®çã«æ£è¦è¡¨ç¾ã§åè£ã grep ãã¦ãã¾ããToggleâ¯Router ãã³ã¼ãçæãã¦ãããããã¡ã½ããåãæ¤ç´¢ããã°ããã¨ããç¹ã§ãèªåçæã®æ©æµãåãã¦ãã¾ãã
è£è¶³
æ£è¦è¡¨ç¾ã§ã®æ¤ç´¢ã¯å½é½æ§ãçºçãããããããæ¬æ¥ã¯ treeâsitter ãªã©ã®ãã¼ãµã使ãã®ãæã¾ããã§ããtreeâsitter ã«ã¯ WASM ãã¤ã³ãã£ã³ã°ããããGo ã§ããã° wazero ãç¨ãã¦å®è¡ãããã¨ãå¯è½ããããã¾ãããã
ä»å¾ã®å±æ
ç¾ç¶ã§ã¯ Toggleâ¯Point ã®åé¤ä½æ¥ã Productâ¯Team ã«å ¨é¢çã«å§ãã¦ãããããå餿¼ããçºçãã㨠Zombieâ¯Flag ãæºã¾ã£ã¦ããã¾ãããã®ã¾ã¾ã§ã¯ Zombieâ¯Flag ã«å¯¾ããæ¬è³ªçãªè§£æ±ºã«ã¯è³ãã¾ãããä»å¾ã¯ãããããã¢ã¯ãã£ããªã¢ããã¼ããæ¤è¨ãã¦ããããã¨èãã¦ãã¾ãã
ããã«ãfeature flag åºç¤ã¯é«ãä¿¡é ¼æ§ãæ ä¿ã§ããªããã°ãªãã¾ãããè©ä¾¡ãã¸ãã¯ã«ãã°ãé害ãããã¨ãToggleâ¯Router ã誤ã£ãå¤ãè¿ãã¦ä¸è¬ã¦ã¼ã¶ã¼ã«å®é¨æ©è½ãå ¬éãã¦ãã¾ããªã©ãé大ãªã¤ã³ã·ãã³ãã¸ç´çµãã¾ããç¾å¨ã¯ãªã¯ã¨ã¹ãæ°ãå¤ããªããã In-Process Evaluation mode ã§éç¨ã§ãã¦ãã¾ãããäºæ¥ãã¹ã±ã¼ã«ããéã«ã¯å¯ç¨æ§ã¨ä¸è²«æ§ã両ç«ãããè¨è¨ãä¸å¯æ¬ ã§ããå°æ¥çã«ã¯ãªã¢ã¼ãè©ä¾¡ã¯ã©ã¹ã¿ã®å°å ¥ããã£ãã·ã¥æ¦ç¥ã®æé©åããã«ãã¾ã¼ã³åé·åãªã©ãè¦éã«å ¥ããåºç¤å ¨ä½ã®èé害æ§ã¨ããã©ã¼ãã³ã¹ãå¼·åãã¦ãããã¨ãèããããããããã¾ããã
ãããã«
é·æã«ãä»ãåãããã ãããããã¨ããããã¾ãããfeature flag 㯠Gartner ã® Hype Cycle ã« 2023,2024 å¹´ã§ âslopeâ¯ofâ¯enlightenmentâ ã«ä½ç½®ä»ããã *11ãCNCF ã§ã¯ OpenFeature ã Incubatingâ¯Project ã«é¸å®ããããªã©ãä¸ççã«ããã«æ³¨ç®ããã¦ããæè¡é åã¨ãªã£ã¦ãã¾ãã䏿¹ã§å½å ã®å ·ä½çãªæ´»ç¨äºä¾ã¯ã¾ã ã¾ã å°ãªããå°å ¥ãèºèºã£ã¦ããéçºãã¼ã ãå¤ãã®ã宿 ã ã¨æãã¾ããæ¬è¨äºãããã©ã³ã¯ãã¼ã¹éçºã¨ featureâ¯flag ãåãå ¥ãã¦éçºè ä½é¨ãåä¸ããããçãã¾ã®ä¸å©ã«ãªãã°å¹¸ãã§ãã
æå¾ã«ãFlagsmith ã® Benâ¯Rometsch æ°ã OpenFeature å ¬å¼ããã°ã«å¯ç¨¿ããè¨äº *12 ããå°è±¡çãªä¸ç¯ãå¼ç¨ãã¾ãã
âIntroducing feature flags will fundamentally change the way you build software, so pulling in the right stakeholders from the beginning is important. Start by creating a working group with representatives from your engineering, QA, product, and DevOps/infrastructure teams. Additionally, youâll need full executive buy-in to bring flags on at scale. This is true from a budget perspective but, just as importantly, from a time perspective, too. Part of the reason the eBay team was so successful with their OpenFeature adoption is because they were given full license to use engineering hours to get it done.â
feature flag ã®å°å ¥ã¯ã½ããã¦ã§ã¢éçºã®å¨ãæ¹ãæ ¹æ¬çã«å¤ãããããåææ®µéããé¢ä¿è ããã£ããå·»ãè¾¼ããã¨ãéè¦ã§ããã¾ãã¯ã¨ã³ã¸ãã¢ãQAããããã¯ããDevOps/ã¤ã³ãã©ã®ä»£è¡¨è ã§ã¯ã¼ãã³ã°ã°ã«ã¼ããçµç¹ãã¾ããããããã«ãå¤§è¦æ¨¡éç¨ã«ã¯äºç®é¢ã ãã§ãªãå·¥æ°ç¢ºä¿ã®è¦³ç¹ã§ãçµå¶å±¤ã®å ¨é¢çãªçè§£ã¨ååãæ¬ ããã¾ãããeBay ãã¼ã ã OpenFeature ãæåãããè¦å ã®ä¸ã¤ã¯ãã¨ã³ã¸ãã¢ãªã³ã°æéãèªç±ã«æå ¥ã§ããç°å¢ããã£ãããã§ãã
newmo ã§ã¯ãCI/CD ã®èªåååºç¤ãèªè¨¼èªå¯ã¨ã³ã³ãã¼ãã³ãé伿ã®ä»çµã¿ãOpenTelemetry/Datadog ã«ãããªãã¶ã¼ãããªãã£ãèªåçæãã¼ã«ãªã©ã® æ¢åã® Platform ããã£ãããããããã®ä¸ã« feature flag åºç¤ãæ§ç¯ãããã¨ãã§ãã¦ãã¾ããã¾ãéè¦ãªã®ã¯ãæè¡ãå°å ¥ãã¦çµããã«ããã®ã§ã¯ãªããç¶ç¶çãªéçºã¸ã®æè³ã¨æ¹åãæãã¾ãªãå§¿å¢ ã§ããPlatform ã¯ä¸æä¸å¤ã§å®æãããã®ã§ã¯ãªããè²ã¦ã使ãè¾¼ã¿ã磨ããããç¶ãããã¨ã§ãã¯ããã¦çµç¹ã¨ãããã¯ãã®é²åãæ¯ããå¼·åãªãã©ã¤ãã¼ã¨ãªãã¾ãã
ãããããåãã¼ã ãææ¦ã®æãæ²ããé«ãçç£æ§ãç¶æããªããæ´»èºãç¶ãããããããPlatformâ¯Team 㯠Platformâ¯Engineering ãæ¨é²ãã¦ããã¾ãã
æ¸ãã人: tobi
*1:Trunk Based Deployment: Introduction
*3:The Ultimate Feature Flag Guide
*4:Discover the OpenFeature Ecosystem
*6:newmo ã®åµæ¥ãæ¯ãã Software Architecture 㨠Platform Engineering
*9:OpenTelemetry Collector ã使ã£ã Cloud Run to Datadog ã®å®è£ ãã¿ã¼ã³
*10:OpenFeature ã¨èªåçæãæ´»ç¨ãããã£ã¼ãã£ã¼ãã©ã°ã®å®£è¨çéç´ç®¡ç
*11:Whatâs New In The 2024â¯Agileâ¯&â¯DevOps Gartner® Hype Cycleâ¢: Featureâ¯Management, Experimentation, andâ¯AI
*12:Scaling Feature Flags eBook: A Roadmap for Safer Releases & Faster Development