[ הרצאה · DOTB Meetup #3 · Web Frameworks ]

The Future of Feature Flags

וידאו · 30 ביולי 2024 · 23:53 · ירדן לייפנפלד

Feature Flags הם לא מתג on/off. ירדן לייפנפלד מראה איך לשחרר בהדרגה, למדוד את ההשפעה, לעשות rollback בלי deploy, ולהימנע מערימת flags בקוד.

צפו בהרצאה · 23:53
תמונה ממוזערת של ההרצאה: The Future of Feature Flags
[ כתבת ההרצאה ]

הסיפור שמאחורי ההרצאה

[ תקציר מהיר ]
  • Feature Flag מאפשר לשנות התנהגות בזמן ריצה ולחשוף פיצ'ר בהדרגה, במקום להעביר את כל המשתמשים מגרסה אחת לשנייה.
  • משתנה סביבה הוא התחלה, אבל flag דינמי עם provider נפרד מאפשר targeting, שינוי בלי restart, וניסוי בלי להכניס מפתח לכל עדכון.
  • OpenFeature מגדיר API ו-SDK סטנדרטיים, כך שאפשר להחליף provider בלי לשכתב את הקוד שקורא ל-flags.
  • OpenTelemetry הופך Feature Flags לדו-כיווניים: אפשר לקשור בין מצב flag למטריקות, traces ושיעור כשלים.
  • Rollout הדרגתי דורש גם משמעת: rollback מהיר במקרה כשל, עקביות למשתמש, ומחיקת flags אחרי שההחלטה כבר התקבלה.

The Future of Feature Flags

Feature Flags נשמעים כמו מתג on/off. ואז מגיע פרודקשן: פיצ’ר חדש עובד אצלכם מקומית, אבל לא ברור מה יעשה ל-100% מהמשתמשים. אם הדרך היחידה שלכם היא deploy לכולם או rollback של כל הגרסה, אתם לא שולטים בחשיפה. אתם מהמרים עליה.

בהרצאה של ירדן לייפנפלד, היא מציגה דרך אחרת לחשוב על שחרור: לא מעבר מ-v1 ל-v2, אלא פיצ’ר בודד שאפשר להפעיל לקבוצה קטנה, למדוד, לכבות ולשנות בלי להכניס כל החלטה ל-PR. הפוקוס הוא על OpenFeature, על targeting דינמי, ועל החיבור בין flags לבין OpenTelemetry.

הנקודה אינה להוסיף עוד if לקוד. להפך. Feature Flag טוב מוציא את ההחלטה הזאת מהמקום שבו היא הופכת למבוך, ונותן לצוות דרך לחקור שינוי בפרודקשן בלי להפוך את כל המשתמשים לניסוי.

לא עוברים גרסה. חושפים יכולת

ירדן פותחת בדוגמה פשוטה: אפליקציית todo שכבר יש לה משתמשים. נוסיף כפתור שמוחק את כל המשימות שהושלמו. אפשר לייצר v2, לפרוס אותה ולהעביר את כולם בבת אחת. אבל אין ודאות שהכפתור באמת מתנהג נכון בפרודקשן, או שהמשתמשים מבינים אותו.

Feature Flag מפרק את ההחלטה. הכפתור כבר נמצא בגרסה שנפרסה, אבל רק חלק מהמשתמשים רואים אותו. אפשר להתחיל ב-10%, לקבל פידבק, לבדוק שגיאות, ואז להרחיב. זאת טכניקה שמשנה התנהגות של מערכת בזמן ריצה ובאופן דינמי. Flag יכול להיות on או off, אבל הוא יכול גם לקבל ערך מספרי או מחרוזת - השאלה החשובה היא מי מקבל איזה ערך ומתי.

היתרון אינו רק זהירות. הוא מאפשר פיתוח מקבילי: קוד יכול להיכנס בלי לחסום שחרור אחר, ותכונה עדיין לא מוכנה יכולה להישאר כבויה. אבל הוא יוצר חוב אם לא מנהלים אותו. Flag אינו מקום להסתיר החלטה לשנים. הוא מנגנון לתהליך החלטה.

משתנה סביבה הוא התחלה, לא סוף הדרך

ירדן מתארת פירמידה של בשלות. בתחתית נמצא משתנה סביבה שמדליק או מכבה פיצ’ר. זה אינו פסול - למשל flag של debug יכול להתאים - אבל שינוי דורש restart. כשצריך להגיב מהר, restart לכל שירות רק כדי לשנות boolean הוא מחיר גבוה.

הרמה הבאה היא dynamic configuration: הערך נשמר במקום שאפשר לשנות בלי restart, למשל database. עדיין יכולה להיות פעולה ידנית, אבל הפיצ’ר כבר דינמי. משם עוברים ל-dynamic evaluation. כאן הערך אינו רק flag גלובלי. הוא מחושב מול context: משתמש, מדינה, יום בשבוע או כל מאפיין אחר.

הבדל חשוב הוא מיקום הלוגיקה. אם הקוד שלכם מלא ב-if customer in legacyCustomers, ההחלטה עדיין גרה באפליקציה. ברמה הדינמית, האפליקציה פונה ל-feature flag provider נפרד, והוא מחשב את הכלל. כך אפשר לשנות targeting בלי לשנות קוד, בלי לחכות ל-PR ובלי להכניס מפתח לכל שינוי של קבוצת לקוחות. אפשר גם לשמור compliance, למשל להציג הודעת cookies למשתמשים באירופה לפי הכללים הרלוונטיים.

OpenFeature מפריד בין הקוד ל-provider

האפליקציה צריכה לשאול שאלה פשוטה: האם להגיש את v1 או v2? בדרך כלל היא עושה זאת דרך SDK שמדבר עם provider. הבעיה מתחילה כשה-SDK וה-provider מגיעים מאותו שירות, וכל הקוד העסקי תלוי ב-API הספציפי שלו. החלפת ספק הופכת לפרויקט rewrite.

OpenFeature מציע שכבת סטנדרט: API יחיד ו-SDKs לשפות שונות. האפליקציה קוראת ל-API האחיד, וה-provider הוא implementation שאפשר להחליף. לפי הדוגמה בהרצאה, אפשר לעבור מ-LaunchDarkly לפתרון אחר כמו FlagD בלי לשנות את הקריאות בקוד העסקי.

הסטנדרט גם מדגיש את ה-EvaluationContext. האפליקציה מעבירה context, ה-provider מפעיל כללים, overrides או חלוקה אחוזית, ומחזיר החלטה. זו תשתית שמאפשרת לצוות להפסיק לקודד ידנית כל exception ולהתמקד במה שהפיצ’ר צריך להוכיח.

Flag בלי מדידה הוא רק ניסוי עיוור

השלב המתקדם אינו רק לחשוף 25% מהתנועה. הוא לדעת מה קרה להם. ירדן מחברת את ה-flags ל-OpenTelemetry, שמאפשר לאסוף logs, traces ומטריקות. כך ה-flag הופך למנגנון דו-כיווני: לא רק נותנים לפיצ’ר החלטה, אלא גם מקבלים מידע על ההשפעה שלה.

בדוגמה של sneaker shop, עלייה בעומס מעלה response time. traces מראים שהזמן נשרף ב-database, ולכן מוסיפים read replicas. אבל לא פותחים אותן לכולם. הגישה ל-replica יושבת מאחורי Feature Flag, ורק משתמשים שנבחרו מגיעים אליה. ה-context חשוב גם לעקביות: משתמש לא אמור לקבל יום אחד נתיב חדש וביום הבא נתיב אחר רק כי החלוקה האקראית השתנתה.

אחרי שמחברים את OpenFeature ל-OpenTelemetry, אפשר לפלח מטריקות לפי מצב ה-flag: מי קיבל replica, מי נשאר במקור, ומה שיעור הכשלים בכל קבוצה. זה ההבדל בין “נראה שזה בסדר” לבין ראיה ישירה שהשינוי משפר או שובר משהו.

Rollout טוב יודע גם לחזור אחורה

בתרחיש של ירדן, ה-read replicas נפתחות ל-25% מהמשתמשים ומופיעים failures. זה לא כשל של Feature Flags. זה בדיוק הערך שלהם: הכשל מוגבל לקבוצה קטנה ומזוהה דרך הטלמטריה. הצוות מכבה את ה-flag לאותה קבוצה, חוזר לדאטאבייס המקורי, ומחזיר את המערכת למצב איטי יותר אבל עובד.

אין deploy חדש ואין שינוי קוד כדי לעשות rollback. מתקנים את הבעיה ב-replica, מנסים שוב על קבוצה קטנה, בודקים שהמערכת יציבה, ואז עולים ל-100%. לפריסה בטוחה של תשתית יש אותו עיקרון כמו בהרצאה על CI/CD מהיר: אין ערך במהירות אם היא פשוט מביאה כשל ללקוחות מוקדם יותר.

אבל התהליך לא נגמר ב-100%. אחרי שהחלופה הוכחה והוחלט להשתמש בה, מוחקים את ה-flag ואת הנתיב הישן. אחרת נוצרים flags מצטברים, A/B tests ונקודות החלטה שאף אחד כבר לא מבין. המצב הזה מקשה על תחזוקה ומעלה סיכון לא פחות מה-deploy הראשוני.

השורה התחתונה

Feature Flags אינם קסם של boolean. הם כלי לניהול סיכון ולהפעלת שיקול דעת בפרודקשן.

  • התחילו מחשיפה קטנה במקום מ-big bang deployment.
  • הוציאו targeting וכללים מהקוד אל provider נפרד כשיש בכך צורך.
  • שמרו context עקבי כדי שהמשתמש לא יקבל חוויה מתחלפת.
  • חברו את מצב ה-flag למטריקות ול-traces כדי למדוד impact אמיתי.
  • כבו מהר כשיש כשל, תקנו, ונסו rollout מחדש.
  • מחקו flags כשסיימו את תפקידם.

לא כל צוות צריך A/B testing מורכב או תשתית ייעודית. כמו שירדן מדגישה, שלב 2 דינמי כבר יכול להיות מצוין. העיקר הוא שהדגל ישמש לקבלת החלטה טובה יותר, ולא יהפוך לעוד תנאי שאיש כבר לא מעז לגעת בו.

"אנחנו יכולים ככה בעצם לבדוק פיצ'רים חדשים על סאבסט של יוזרים."

- ירדן לייפנפלד

"לא דורש לי deploy, לא דורש ממני לשנות קוד."

- ירדן לייפנפלד

"וכמובן לא נשכח למחוק את ה-feature flag."

- ירדן לייפנפלד

"שלב 2 זה מצוין."

- ירדן לייפנפלד
[ פרקי ההרצאה ]
  1. 00:01:32
    מגרסה חדשה לפיצ'ר בודד
    דוגמת todo app מראה למה אפשר לחשוף כפתור חדש לחלק מהמשתמשים במקום להעביר את כולם בבת אחת ל-v2.
  2. 00:03:18
    ארבע רמות של Feature Flags
    מהמתג שמבוסס על משתנה סביבה, דרך configuration דינמי, ועד evaluation עם context וטלמטריה.
  3. 00:06:00
    Dynamic Evaluation ו-targeting
    provider נפרד מחשב את הערך לפי context, וכך מחליפים תנאי בקוד בחשיפה לקבוצת משתמשים, למדינה או ל-10% מהתנועה.
  4. 00:09:16
    OpenFeature כשכבת סטנדרט
    API אחיד ו-SDK מאפשרים להפריד את האפליקציה מה-provider ולהחליף שירות Feature Flags בלי לשנות את הקוד העסקי.
  5. 00:12:23
    OpenTelemetry הופך rollout למדיד
    logs, traces ומטריקות מאפשרים לקשור בין השפעת flag לבין ביצועים, התנהגות משתמשים ושיעורי כשל.
  6. 00:15:42
    Read replicas מאחורי flag
    דוגמה לפתרון עומס בדאטאבייס: חושפים replicas רק לקבוצה קטנה, בודקים impact ושומרים על חוויה עקבית למשתמש.
  7. 00:18:16
    Rollback בלי deploy וניקוי הדגל
    כשל אצל 25% מהמשתמשים מאפשר לחזור מיד למקור, לתקן, לנסות שוב ולהסיר את ה-flag לאחר ההחלטה.
[ נושאים ]

מה כוסה בהרצאה

#בקאנד וענן #מתודולוגיה #DevOps #Architecture
[ שאלות נפוצות ]

שאלות מההרצאה

מה ההבדל בין Feature Flag למשתנה סביבה?

משתנה סביבה יכול להדליק או לכבות פיצ'ר, אבל לרוב דורש restart של האפליקציה או ה-pod כדי לשנות אותו. Feature Flag דינמי נשען על configuration או provider נפרד, ולכן אפשר לשנות את הערך בזמן ריצה. הוא גם יכול להחזיר יותר מ-on או off ולהחליט לפי context כמו משתמש, מיקום או אחוז מהתנועה.

איך Feature Flags מפחיתים סיכון בפריסה?

במקום לחשוף שינוי לכל המשתמשים, אפשר להתחיל בקבוצה קטנה, למשל 10% או 25%, ולבדוק האם הפיצ'ר עובד ומה המשתמשים חווים. בדוגמת ה-read replicas, הכשל התגלה רק בקבוצה שקיבלה את הנתיב החדש. אפשר היה לכבות את ה-flag אצל אותה קבוצה בלי deploy, לתקן את הבעיה ולנסות rollout נוסף.

למה צריך OpenFeature אם כבר יש provider ל-Feature Flags?

OpenFeature מספק סטנדרט ל-API ול-SDK שבין האפליקציה ל-provider. לפי ירדן, השכבה הזו מאפשרת להשתמש בשירותים ובפתרונות שונים בלי לכתוב מחדש את הקריאות בקוד העסקי בכל מעבר. היא אינה מחליפה בהכרח את ה-provider עצמו, אלא מפרידה בין האפליקציה לבין המימוש שמחשב את הערך של ה-flag.

איך מונעים מ-Feature Flags להפוך לבלגן בקוד?

מוציאים ככל האפשר את חוקי ה-targeting וה-A/B testing מהקוד אל provider, ומתייחסים לכל flag כאל מנגנון זמני עם owner ותנאי הסרה. ירדן מדגישה שבסיום rollout מוצלח צריך למחוק את ה-flag ולהשאיר את ההתנהגות שנבחרה. אחרת, שנה אחר כך קשה להבין למה חלק מהדאטאבייס או מהלוגיקה עדיין מוסתר מאחורי flag.

[ קהילה ]

רוצה לדבר על ההרצאה?

הצטרף לקהילת המפתחים שלנו ב-WhatsApp.