מדריך

איך להגדיל SaaS אחרי ההשקה בלי לשבור את המוצר

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

Have a nice dayHave a nice day13 דק' קריאה
איך להגדיל SaaS אחרי ההשקה בלי לשבור את המוצר

כולם חוגגים את ההשקה. כמעט אף אחד לא מזהיר אתכם מפני החלק שמגיע אחר כך — אותה שנה מוזרה ומתוחה שבה המוצר שהביא לכם את מאה הלקוחות הראשונים מתחיל להתקפל תחת המשקל של האלף הבאים. שום דבר דרמטי לא קורה. הדברים פשוט נעשים איטיים יותר, רעועים יותר, קשים יותר לשינוי. ביום שלישי אחד אתם מבינים שפיצ'ר שפעם לקח יום עכשיו לוקח שבוע, ואף אחד לא יודע להגיד בדיוק למה. שם, ולא בהשקה, רוב מוצרי ה-SaaS נמכרים או אובדים בשקט.

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

אז זהו המדריך שהיינו רוצים שיותר יזמים יקבלו לפני שהסדקים הופיעו. הוא לא עוסק ב-hyperscale, ב-Kubernetes או במה שאיזה יוניקורן עשה בחמישים מיליון משתמשים. הוא עוסק באמצע המשעמם והמכריע — המעבר מזה עובד לכמה לזה עובד לרבים — בלי לכתוב הכל מחדש, בלי להבריח את הלקוחות שלכם, ובלי לשרוף את הצוות. המטרה אינה ארכיטקטורה מושלמת. היא מוצר שממשיך לצמוח במקום כזה שמתחיל בשקט להישבר.

מה באמת נשבר כש-SaaS גדל

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

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

המוצר שלכם לא נשבר כי קיבלתם יותר משתמשים. הוא נשבר כי המשתמשים האלה שונים זה מזה הרבה יותר משהיו אי פעם הראשונים שלכם.
מה שאנחנו אומרים ליזמים בנקודת השבירה

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

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

המלכודת של פתרון בעיות שעדיין אין לכם

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

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

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

מדדו לפני שאתם משנים משהו

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

אינכם זקוקים ל-observability stack מפואר כדי להתחיל. אתם זקוקים לשלושה מספרים משעממים מול העיניים, כל הזמן. אילו endpoints הם האיטיים ביותר, וכמה איטיים תחת תעבורה אמיתית. אילו שאילתות לבסיס הנתונים לוקחות הכי הרבה זמן כולל — לא השאילתה הבודדת האיטית ביותר, אלא זו שהזמן שלה מצטבר על פני אלפי קריאות. והיכן באמת קורות שגיאות, עם מספיק הקשר כדי לשחזר אותן. עם שלושת אלה, הערפל בדרך כלל מתבהר תוך יום.

  1. 1
    הפעילו ניטור בסיסי
    זמני תגובה לכל endpoint, שיעורי שגיאות, ורישום שאילתות איטיות בבסיס הנתונים. כלים מתארחים עושים זאת תוך אחר צהריים. אי אפשר לשפר מספר שאינכם רואים.
  2. 2
    מצאו את שלושת הראשונים האמיתיים
    מיינו לפי הזמן הכולל הנצרך, לא לפי תחושת בטן. שלושה עבריינים כמעט תמיד אחראים לרוב הכאב. רשמו אותם — זו מפת הדרכים האמיתית שלכם.
  3. 3
    תקנו אחד, מדדו שוב
    שנו דבר אחד בלבד, ואז בדקו מחדש את המספרים. ודאו שזה עזר לפני שאתם ממשיכים. שני שינויים בבת אחת ולעולם לא תדעו איזה מהם הועיל.
  4. 4
    עצרו כשזה מספיק טוב
    הגדירו 'מהיר מספיק' לפני שאתם מתחילים — נניח, כל דף מתחת לשנייה בעומס הנוכחי. מעבר לזה, אופטימיזציה היא בזבוז זמן, לא ניצחון.

הצעד האחרון חשוב יותר משנראה. עבודת ביצועים ממכרת באמת; תמיד יש עוד מילישנייה לגרד. אבל הלקוחות שלכם לא מרגישים את ההבדל בין 200ms ל-120ms, והשעות שאתם מבזבזים ברדיפה אחריו הן שעות שלא הוקדשו לפיצ'ר שבאמת היה מגדיל את העסק. מדדו, תקנו את שלושת הראשונים, הכריזו על ניצחון, המשיכו הלאה.

בסיס הנתונים הוא כמעט תמיד הקיר הראשון

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

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

יש כאן רצף שכדאי להישען עליו, ומשתלם לעקוב אחריו לפי הסדר במקום לקפוץ לסוף. תקנו את השאילתות קודם — אינדקסים, N+1, הדוח האיטי. אחר כך הוסיפו caching לנתונים שנקראים כל הזמן אבל משתנים לעתים רחוקות. רק אחרי זה הגיוני לדבר על read replicas, instances גדולים יותר, או הפרדת נתונים. רוב מוצרי ה-SaaS לעולם לא זקוקים לשלבים המאוחרים. הם פשוט היו זקוקים שהראשונים ייעשו כראוי.

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

להגדיל את המוצר פירושו להגדיל את האופן שבו אתם משנים אותו

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

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

  • סוויטת בדיקות המכסה את קומץ התהליכים שהיו קטסטרופליים אם היו נשברים — התחברות, תשלום, פעולת ליבה. לא הכל; את הבודדים הקריטיים.
  • דיפלוים שרצים על לחיצת כפתור, לא טקס, כך ששליחה קטנה ותכופה הופכת לבטוחה במקום לדורשת עצבים.
  • דרך מהירה לבצע rollback, כך שגרסה גרועה היא אירוע של חמש דקות, לא תקרית של לילה שלם.
  • Feature flags, כך שתוכלו לשלוח קוד לכמה לקוחות קודם ולכבות אותו מיד אם הוא מתנהג לא כראוי.
  • מספיק תיעוד כך שחופשה של אדם אחד לא תקפיא תחום שלם של המוצר.

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

סיפור קצר מנקודת השבירה

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

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

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

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

מתי באמת הגיע הזמן לבנות מחדש חלק

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

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

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

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

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

פגעתם בקיר ולא בטוחים אם זה תיקון או בנייה מחדש?

זו ההחלטה שיקר לטעות בה וזול לקלוע בה. נמדוד היכן המוצר שלכם באמת נמתח ונאמר לכם בכנות אם זה תיקון של יומיים או משהו עמוק יותר — לפני שמישהו כותב שורה של קוד חדש.

ראו כיצד אנחנו ניגשים להגדלת תוכנה

שאלות נפוצות

איך אדע אם ה-SaaS שלי עומד לפגוע בקיר הגדלה?
שימו לב לתסמינים איטיים, לא לקריסות: דפים שנעשים איטיים בהדרגה, אותם באגים שחוזרים, דיפלוים שעכשיו מרגישים מסוכנים, וכרטיסי תמיכה שגדלים מהר יותר ממספר המשתמשים שלכם. אלה בדרך כלל מופיעים הרבה לפני כל תקלה דרמטית. הפעלת ניטור בסיסי מוקדם פירושה שאתם רואים את הקיר מתקרב במקום לפגוע בו.
האם עלי לעבור למיקרו-שירותים כדי להגדיל?
כמעט בוודאות לא עדיין, ואולי אף פעם. מיקרו-שירותים פותרים בעיות ארגוניות ובעיות קנה מידה שלרוב מוצרי ה-SaaS הצומחים בעצם אין, תוך הוספת המון מורכבות יומיומית. מונולית נקי ומובן היטב שתוכלו לשנות במהירות יגדל טוב יותר ממערכת מבוזרת שאתם חוששים לגעת בה. פנו לארכיטקטורה הזו רק כשבעיה ספציפית ומדודה דורשת זאת.
האם זול יותר לבצע אופטימיזציה לקוד או פשוט לקנות שרת גדול יותר?
אופטימיזציה קודם, כמעט תמיד. שרת גדול יותר הוא עלות חודשית חוזרת שקונה לכם מעט מרחב נשימה; תיקון אינדקס חסר או שאילתת N+1 הוא בדרך כלל מאמץ חד-פעמי שלא עולה כלום אחר כך ולעתים קרובות נותן רווח גדול בהרבה. הגדילו את החומרה רק כשהקוד והשאילתות כבר נקיים.
מתי כתיבה מחדש מלאה היא באמת ההחלטה הנכונה?
לעתים רחוקות, ולחלק אחד בכל פעם במקום לכל המוצר. בנו מחדש רכיב כששינוי שלו הפך באופן עקבי לאיטי ומסוכן יותר מהחלפתו, אותם באגים חוזרים, וכבר מיציתם את התיקונים הזולים. גם אז, החליפו את הרכיב הבודד הזה מאחורי גבול ברור בזמן שהשאר ממשיך לרוץ. הכתיבה מחדש המלאה מאפס היא בדרך כלל מלכודת של שנה.
כמה עלי להשקיע בהגדלה לפני שיש לי את המשתמשים?
מעט מאוד, במכוון. בנו משהו נקי ופשוט שתוכלו לשנות מהר, הוסיפו ניטור בסיסי כדי שתוכלו לראות בעיות מתקרבות, ומלבד זאת התנגדו לבניית תשתית לקנה מידה שלא הגעתם אליו. ההכנה הטובה ביותר להגדלה אינה ארכיטקטורה מורכבת — היא מוצר פשוט וצוות שיכול לשנות אותו בבטחה כשצווארי הבקבוק האמיתיים מופיעים.
Have a nice day
Have a nice day
המערכת

‏Have a nice day הוא סטודיו תוכנה שעוזר לעסקים קטנים ובינוניים לעבור לדיגיטל — אוטומציה, בינה מלאכותית ותוכנה בהתאמה אישית שעובדת בשגרת היום-יום, לא רק על שקפים.

שירותים רלוונטיים