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

כולם חוגגים את ההשקה. כמעט אף אחד לא מזהיר אתכם מפני החלק שמגיע אחר כך — אותה שנה מוזרה ומתוחה שבה המוצר שהביא לכם את מאה הלקוחות הראשונים מתחיל להתקפל תחת המשקל של האלף הבאים. שום דבר דרמטי לא קורה. הדברים פשוט נעשים איטיים יותר, רעועים יותר, קשים יותר לשינוי. ביום שלישי אחד אתם מבינים שפיצ'ר שפעם לקח יום עכשיו לוקח שבוע, ואף אחד לא יודע להגיד בדיוק למה. שם, ולא בהשקה, רוב מוצרי ה-SaaS נמכרים או אובדים בשקט.
ישבנו עם הרבה יזמים בדיוק בנקודה הזו. הם לא נכשלים — וזה הדבר המבלבל. ההכנסות עולות, הצוות גדל, ההדגמות הולכות טוב. אבל מתחת לפני השטח, המוצר גונח. כרטיסי תמיכה מטפסים מהר יותר מהמשתמשים. דיפלוים שפעם היו משעממים מגיעים עכשיו עם נשימה עצורה. בסיס הקוד שהרגיש חכם לפני שנה מרגיש עכשיו כמו שדה מוקשים שבו כל שינוי מסכן להפעיל משהו אחר. הם לא עשו שום דבר לא נכון. הם פשוט גדלו מעבר למה שבנו, ואף אחד לא אמר להם שזה אמור לקרות.
אז זהו המדריך שהיינו רוצים שיותר יזמים יקבלו לפני שהסדקים הופיעו. הוא לא עוסק ב-hyperscale, ב-Kubernetes או במה שאיזה יוניקורן עשה בחמישים מיליון משתמשים. הוא עוסק באמצע המשעמם והמכריע — המעבר מזה עובד לכמה לזה עובד לרבים — בלי לכתוב הכל מחדש, בלי להבריח את הלקוחות שלכם, ובלי לשרוף את הצוות. המטרה אינה ארכיטקטורה מושלמת. היא מוצר שממשיך לצמוח במקום כזה שמתחיל בשקט להישבר.
מה באמת נשבר כש-SaaS גדל
הנה החלק שמפתיע יזמים יותר מכל: בעיות הגדלה כמעט אף פעם לא מגיעות כתקלה הדרמטית שאתם מתכוננים אליה. השרת לא עולה באש. במקום זאת, המוצר מפתח מעין חום נמוך. דפים שנטענו מיד מתחילים לקחת שלוש שניות. דוח שרץ בסדר ללקוחות הראשונים נכשל ב-timeout עבור הגדול שזה עתה חתם. אותו באג חוזר שוב ושוב כי שני חלקים של הקוד תלויים זה בזה בסתר באופן שאף אחד לא תיעד.
מה שבאמת נשבר זה לעתים רחוקות השרתים שלכם — אלה ההנחות שלכם. בהתחלה בניתם עבור הצורה של המשתמשים הראשונים: כמה חשבונות, מעט נתונים, תהליכי עבודה פשוטים, כולם בערך אותו דבר. הצמיחה לא רק מוסיפה עוד מאותו דבר. היא מוסיפה מגוון. לקוח עם פי עשרה נתונים. צוות שמשתמש בפיצ'ר באופן שמעולם לא דמיינתם. שיא ב-9 בבוקר ביום שני כשכולם מתחברים בבת אחת. כל אחד מהם מפר בשקט הנחה שהוטמעה בקוד שלכם לפני שנה, כשהפרה שלה הייתה בלתי נתפסת.
“המוצר שלכם לא נשבר כי קיבלתם יותר משתמשים. הוא נשבר כי המשתמשים האלה שונים זה מזה הרבה יותר משהיו אי פעם הראשונים שלכם.”
ארבעת המקומות שבהם זה נוטה להופיע קודם הם צפויים. בסיס הנתונים הוא כמעט תמיד הקנרית — שאילתות שהיו מיידיות בטבלאות קטנות זוחלות ככל שהנתונים גדלים. ה-endpoint האיטי: דף אחד או שניים שעושים יותר מדי עבודה לכל בקשה, בסדר עד שהתעבורה מצטברת. הדיפלוי השברירי, שבו לשלוח כל דבר הפך למפחיד כי הקוד מסובך מדי מכדי להבין אותו. ועומס התמיכה, שהוא בכלל לא תשתית אבל הוא האות המוקדם האמיתי ביותר לכך שהמוצר כבר לא מתאים לאופן שבו אנשים באמת משתמשים בו.

המלכודת של פתרון בעיות שעדיין אין לכם
לפני שנדבר על תיקון דברים, אזהרה שהצילה יותר מוצרים מכל אופטימיזציה. האיום הגדול ביותר על SaaS צומח אינו התעלמות מקנה המידה — אלא רדיפה אחריו מוקדם מדי. ברגע שיזם מרגיש את ההאטה הראשונה, האינסטינקט הוא לפנות לארכיטקטורה שקרא עליה בבלוג הנדסי מפורסם. מיקרו-שירותים. תור הודעות. הקמה רב-אזורית. שארדינג של בסיס הנתונים לפני שיש בו מיליון שורות.
ככה אתם מבזבזים שישה חודשים והון בבניית תשתית עבור קנה מידה שלא הגעתם אליו, בזמן שהמוצר האמיתי מפסיק לנוע. גרוע מכך, הפכתם עכשיו כל שינוי עתידי לקשה יותר, כי מערכת מבוזרת מורכבת בהרבה לבנייה ולדיבוג מהפשוטה שהייתה לכם. החלפתם בעיה שעדיין לא הייתה לכם בבעיה מובטחת שיש לכם היום: שום דבר לא נשלח.
המשמעת כאן זהה לזו שיוצרת מוצרים טובים מלכתחילה: פתרו את הבעיה שלפניכם, לא את זו שמחמיא לכם לדמיין. מונולית משעמם ומובן היטב שתוכלו לשנות במהירות יגדל טוב יותר ממערכת מבוזרת אופנתית שאתם חוששים לגעת בה. מורכבות היא עלות שאתם משלמים כל יום, לא רכישה חד-פעמית.
מדדו לפני שאתם משנים משהו
כמעט כל יזם שאנחנו פוגשים בשלב הזה משוכנע שהוא יודע היכן הבעיה. הם טועים בכמחצית מהמקרים — לא כי הם רשלנים, אלא כי האינטואיציה היא פרופיילר נורא. החלק בקוד שמרגיש איטי לרוב בסדר; האשם האמיתי הוא איזו שאילתה שקטה שרצה ארבעים פעם בדף שאף אחד לא חשב עליו. אי אפשר לתקן את מה שלא מדדתם, וניחוש כאן הוא הדרך שבה צוותים מבזבזים שבועות באופטימיזציה של הדבר הלא נכון.
אינכם זקוקים ל-observability stack מפואר כדי להתחיל. אתם זקוקים לשלושה מספרים משעממים מול העיניים, כל הזמן. אילו endpoints הם האיטיים ביותר, וכמה איטיים תחת תעבורה אמיתית. אילו שאילתות לבסיס הנתונים לוקחות הכי הרבה זמן כולל — לא השאילתה הבודדת האיטית ביותר, אלא זו שהזמן שלה מצטבר על פני אלפי קריאות. והיכן באמת קורות שגיאות, עם מספיק הקשר כדי לשחזר אותן. עם שלושת אלה, הערפל בדרך כלל מתבהר תוך יום.
- 1הפעילו ניטור בסיסיזמני תגובה לכל endpoint, שיעורי שגיאות, ורישום שאילתות איטיות בבסיס הנתונים. כלים מתארחים עושים זאת תוך אחר צהריים. אי אפשר לשפר מספר שאינכם רואים.
- 2מצאו את שלושת הראשונים האמיתייםמיינו לפי הזמן הכולל הנצרך, לא לפי תחושת בטן. שלושה עבריינים כמעט תמיד אחראים לרוב הכאב. רשמו אותם — זו מפת הדרכים האמיתית שלכם.
- 3תקנו אחד, מדדו שובשנו דבר אחד בלבד, ואז בדקו מחדש את המספרים. ודאו שזה עזר לפני שאתם ממשיכים. שני שינויים בבת אחת ולעולם לא תדעו איזה מהם הועיל.
- 4עצרו כשזה מספיק טובהגדירו 'מהיר מספיק' לפני שאתם מתחילים — נניח, כל דף מתחת לשנייה בעומס הנוכחי. מעבר לזה, אופטימיזציה היא בזבוז זמן, לא ניצחון.
הצעד האחרון חשוב יותר משנראה. עבודת ביצועים ממכרת באמת; תמיד יש עוד מילישנייה לגרד. אבל הלקוחות שלכם לא מרגישים את ההבדל בין 200ms ל-120ms, והשעות שאתם מבזבזים ברדיפה אחריו הן שעות שלא הוקדשו לפיצ'ר שבאמת היה מגדיל את העסק. מדדו, תקנו את שלושת הראשונים, הכריזו על ניצחון, המשיכו הלאה.
בסיס הנתונים הוא כמעט תמיד הקיר הראשון
אם היינו צריכים להמר על כסף היכן SaaS צומח פוגע בתקרה האמיתית הראשונה שלו, היינו מהמרים על בסיס הנתונים בכל פעם. זהו החלק האחד במערכת שבו החלטות מוקדמות קטנות מצטברות הכי קשה. שאילתה ללא אינדקס רצה בהרף עין על אלף שורות ונתקעת על מיליון. הקוד לא השתנה. הנתונים השתנו — והנתונים רק גדלים.
החדשות הטובות הן שבסיס הנתונים הוא גם המקום שבו חיים התיקונים הזולים ביותר ובעלי ההשפעה הגבוהה ביותר. הקלאסי הוא האינדקס החסר: שורה אחת שהופכת שאילתה של כמה שניות למיידית, כי בסיס הנתונים מפסיק לסרוק כל שורה כדי למצוא את המעטות שהוא צריך. ממש אחריו נמצאת בעיית שאילתת N+1 — דף שבמקום לשאול שאלה אחת, שואל בשקט את בסיס הנתונים את אותה שאלה קטנה מאות פעמים בלולאה. שניהם נפוצים, שניהם בלתי נראים עד שמסתכלים, ושניהם בדרך כלל תיקון של יום אחד ברגע שמצאתם אותם.
יש כאן רצף שכדאי להישען עליו, ומשתלם לעקוב אחריו לפי הסדר במקום לקפוץ לסוף. תקנו את השאילתות קודם — אינדקסים, N+1, הדוח האיטי. אחר כך הוסיפו caching לנתונים שנקראים כל הזמן אבל משתנים לעתים רחוקות. רק אחרי זה הגיוני לדבר על read replicas, instances גדולים יותר, או הפרדת נתונים. רוב מוצרי ה-SaaS לעולם לא זקוקים לשלבים המאוחרים. הם פשוט היו זקוקים שהראשונים ייעשו כראוי.

להגדיל את המוצר פירושו להגדיל את האופן שבו אתם משנים אותו
הנה השינוי שתופס יזמים לא מוכנים: מעבר לנקודה מסוימת, הגדלה מפסיקה לעסוק במוצר שמטפל ביותר משתמשים ומתחילה לעסוק בצוות שלכם שמטפל ביותר שינוי. כשזה היה אתם ומפתח אחד, כולם החזיקו את כל המערכת בראש. יכולתם לשנות כל דבר כי ידעתם במה זה ייגע. בחמישה או עשרה אנשים, המודל המנטלי הזה מתנפץ — והקוד שהניח שכולם יודעים הכל הופך לנטל.
זו הסיבה האמיתית שדיפלוים נעשים מפחידים. זה לא שהקוד נעשה גרוע יותר בן לילה; זה שאף אחד כבר לא יכול לחזות במלואו את רדיוס הפיצוץ של שינוי. התיקון אינו גבורה או הקפאה של שליחת קוד. זו השקעה בפיגומים הלא זוהרים שמאפשרים לצוות גדול יותר לנוע בלי לדרוך זה על זה: סוויטת בדיקות אוטומטית שתופסת את השבירה המובנת מאליה, דיפלוים שהם שגרה במקום טקס, ודרך לכבות גרסה גרועה תוך שניות במקום להיכנס לפאניקה.
- סוויטת בדיקות המכסה את קומץ התהליכים שהיו קטסטרופליים אם היו נשברים — התחברות, תשלום, פעולת ליבה. לא הכל; את הבודדים הקריטיים.
- דיפלוים שרצים על לחיצת כפתור, לא טקס, כך ששליחה קטנה ותכופה הופכת לבטוחה במקום לדורשת עצבים.
- דרך מהירה לבצע rollback, כך שגרסה גרועה היא אירוע של חמש דקות, לא תקרית של לילה שלם.
- Feature flags, כך שתוכלו לשלוח קוד לכמה לקוחות קודם ולכבות אותו מיד אם הוא מתנהג לא כראוי.
- מספיק תיעוד כך שחופשה של אדם אחד לא תקפיא תחום שלם של המוצר.
שום דבר מזה לא מופיע בהדגמה. שום דבר מזה לא מוסיף ישירות פיצ'ר. וזו בדיוק העבודה שמפרידה בין מוצר שממשיך להאיץ לבין כזה שזוחל לאט יותר עם כל גיוס חדש. הצוותים שמגדילים היטב הם אלה שמתייחסים ליכולת שלהם לשנות את המוצר בבטחה כפיצ'ר בפני עצמו — כי בקנה מידה, זה בדיוק מה שזה.
סיפור קצר מנקודת השבירה
כדי להפוך את זה למוחשי, הנה תרכובת השאובה מעבודה שעשינו — הפרטים מטושטשים, הצורה נאמנה למציאות. SaaS קטן לניהול צוותי שירות שטח השיק היטב וגדל לכמה מאות חברות משלמות. היזמים היו נרגשים ומותשים במידה שווה. ואז חתם הלקוח הגדול ביותר שלהם אי פעם: חברה עם יותר משתמשים ויותר נתונים היסטוריים מעשרת הלקוחות הקודמים שלהם יחד.
תוך שבוע, הדאשבורד שכולם חיו בו האט לזחילה עבור אותו לקוח — ובאופן מוזר, גם עבור כל השאר. כרטיסי תמיכה זינקו. היזמים הניחו שהם זקוקים לשרת גדול בהרבה והתכוננו לארכיטקטורה מחדש כואבת ויקרה. זה היה הרגע שבו הוזמנו, והאינסטינקט היה מובן אך שגוי.
לא נגענו בארכיטקטורה. הפעלנו רישום שאילתות איטיות וצפינו במשך אחר צהריים. האשם היה קטן עד כדי מבוכה כמעט: הדאשבורד הראשי טען את רשימת המשימות של כל משתמש בתבנית N+1 קלאסית, מפעיל שאילתה אחת לכל משימה. ללקוח קטן זה אמר כמה עשרות שאילתות לא מזיקות. עבור הענק החדש, זה אמר אלפים לכל טעינת דף — שעל תשתית משותפת, גרר את כל המערכת למטה עבור כולם.
הלקח שהיזמים לקחו לא היה טכני. הוא היה שבעיית ההגדלה המפחידה שדמיינו — זו שדרשה בנייה מחדש וגיוס — הייתה, כשנמדדה, תיקון של יומיים שמסתתר מאחורי תסמין מפחיד. הם עמדו לבזבז חודשים בפתרון הבעיה הלא נכונה. הפער הזה, בין המשבר המדומיין לזה שנמדד, הוא המקום שבו רוב כסף ההגדלה מתבזבז.
מתי באמת הגיע הזמן לבנות מחדש חלק
כל הזהירות הזו לגבי הגדלה מוקדמת מדי עלולה להיקרא כלעולם אל תעשו ריפקטור, לעולם אל תבנו מחדש. זה לא זה. לפעמים חלק מהמוצר באמת הגיע לסוף חייו, ולטלא אותו שוב היא הבחירה היקרה. הטריק הוא להבחין בין מגבלה מבנית אמיתית לבין כאבי גדילה רגילים שתיקון מדוד היה מטפל בהם.
האות הכן הוא זה: בנו מחדש רכיב כשעלות השינוי שלו הפכה באופן עקבי גבוהה יותר מעלות החלפתו. לא כשהוא מכוער — קוד מכוער שיציב ונוגעים בו לעתים רחוקות הוא בסדר. אתם מחפשים חלק במערכת שבו כל שינוי איטי ומסוכן, שבו אותם באגים חוזרים שוב ושוב, שבו מפתחים חדשים לא יכולים לעבוד בבטחה, ושבו כבר ניסיתם את התיקונים הזולים ופגעתם בקיר. כשכמה מאלה נכונים בו זמנית, כתיבה מחדש ממוקדת של החלק האחד הזה היא המהלך הנכון.
| אות | כנראה רק תיקון | כנראה בנייה מחדש |
|---|---|---|
| תסמין | דף או שאילתה איטיים אחד | כל שינוי בתחום איטי ומסוכן |
| באגים | מדי פעם, ניתנים לתיקון | אותם באגים חוזרים שוב ושוב |
| תיקונים זולים | עדיין לא נוסו | כבר מוצו, עדיין תקועים |
| היקף | מוגבל לפיצ'ר אחד | מתפשט על פני כל המודול |
| המהלך הנכון | מדדו וטלאו | בנו מחדש את החלק האחד הזה, במכוון |
וכשאתם אכן בונים מחדש, בנו מחדש חלק — לא את המוצר. הכתיבה מחדש המלאה מאפס היא שירת הסירנה של ההגדלה, הדבר שמרגיש נקי ובסופו של דבר מטביע שנה בזמן שמתחרים שולחים. החליפו את הרכיב הרקוב האחד, מאחורי גבול ברור, בזמן ששאר המוצר ממשיך לרוץ ולהרוויח. כירורגי, לא הירואי.

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

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