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

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

מתחילים בפעולת המשתמש המרכזית

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

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

מציינים מספרים עם יחידות והנחות

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

Illustrative assumptions:
100,000 active users / day
20 messages / active user / day
2,000,000 messages / day
Average: about 23 messages / second
Peak: estimate separately, do not equate with average

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

מגדירים מה חייב להיות נכון

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

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

בונים מסלול בסיסי לפני אופטימיזציה

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

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

מתכננים גם את מה שלא יודעים

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

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

תרגול של עשר דקות

בחרו שירות מוכר וכתבו: שתי פעולות משתמש, שלושה אילוצים, שני אומדנים ושלוש תכונות נכונות. ציירו זרימה אחת והסבירו שני trade-offs. עכשיו בקשו ממישהו לשנות אילוץ ובדקו אם אתם יודעים לשנות את התכנון בלי להתחיל הכול מחדש.

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