מה שנשבר ראשון כשמתעלמים מ-API Limits
חברה שמריצה שלוש אינטגרציות במקביל - סנכרון ERP לילי, Webhook ממערכת תשלומים, ולוח בקרה חיצוני שמושך נתונים כל חמש דקות - לא נכשלת בהדרגה. היא עובדת מצוין עד שהיא חוצה סף, ואז כל קריאת API נוספת נדחית עם קוד REQUEST_LIMIT_EXCEEDED עד לאיפוס היומי. אין התראה מוקדמת מובנית שמונעת את זה מראש - יש רק Dashboard שאפשר להסתכל בו, אם מישהו בנה תהליך שבודק אותו.
הכשל הזה שונה מרוב הכשלים בפרויקטי Salesforce כי הוא לא תלוי בקוד גרוע או בעיצוב עקום. הוא תלוי בהצטברות: אינטגרציה חדשה נבנית תמיד מול המצב הנוכחי, בלי לבדוק כמה מהתקציב היומי כבר נצרך על ידי תהליכים קיימים. התוצאה היא שהאינטגרציה החמישית "שוברת" את הארבע שקדמו לה, למרות שאף אחת מהן לא השתנתה.
מפת הגבולות שרלוונטית בפועל
לא כל Limit שקיים ב-Salesforce משנה באותה מידה לתכנון אינטגרציות. אלה שבאמת קובעים ארכיטקטורה:
| סוג המגבלה | מה הוא מודד | למי הוא פוגע ראשון |
|---|---|---|
| API Requests היומי | סך קריאות REST/SOAP ב-24 שעות | כל אינטגרציה סינכרונית שרצה בתדירות גבוהה |
| Bulk API Batches | מספר Batches פתוחים/יומיים | תהליכי Batch לילה שמזינים נתוני היסטוריה |
| Concurrent Long-Running Requests | קריאות שרצות יותר מ-20 שניות במקביל | דוחות כבדים או Apex synchronous מורכב |
| Platform Event Delivery | נפח אירועים ליום למנוי | ארכיטקטורות Event-Driven בין Salesforce למערכות חוץ |
| SOQL Rows ל-Transaction | שורות שנשלפות בטרנזקציה בודדת (50,000) | לוגיקת Apex שמריצה שאילתות בתוך לולאה |
הטבלה הזו היא לא תיעוד גנרי - היא סדר עדיפויות. ארגון שמתכנן אינטגרציה חדשה צריך לבדוק קודם כל את שתי השורות הראשונות, כי הן אלה שנחסמות בפועל בייצור. שאר המגבלות משפיעות בעיקר על ביצועים, לא על זמינות.
תקציב קריאות: איך בונים אותו נכון
הכלי המרכזי למניעת חסימה הוא לא ניטור אחרי העובדה אלא תקציב מוגדר מראש לכל צרכן API. העיקרון: כל מערכת חיצונית, כל Integration User וכל תהליך מתוזמן מקבלים הקצאה מוגדרת מתוך המכסה הכוללת, ולא "כמה שצריך".
בניית התקציב כוללת שלושה שלבים:
- מיפוי צרכנים - רשימה של כל תהליך שקורא ל-API: אינטגרציות חיצוניות, Scheduled Apex, Data Loader ידני, כלי BI. לכל אחד יש Integration User נפרד כדי שאפשר יהיה לבודד צריכה ב-Event Monitoring.
- חישוב עומס לפי נפח עסקי, לא לפי הנחה - כמה רשומות עוברות ביום, כמה קריאות נדרשות לרשומה (כולל שליפת Related Lists), ומה קורה בשיא (סוף רבעון, Black Friday, סגירת חודש).
- הקצאת רזרבה - לא מחלקים 100% מהמכסה בין התהליכים הקיימים. משאירים 15%-20% כרזרבה לתהליכי חירום, דוחות אד-הוק ותחזוקה - אחרת כל תוספת קטנה דוחפת את הארגון לחריגה.
מי שרוצה להעמיק בעיצוב השכבה שמנהלת את התקציב הזה ברמת הפלטפורמה כדאי שיקרא את מדריך ארכיטקטורת CRM, שם מוצגת החלוקה בין שכבת אינטגרציה לשכבת עסק.
REST מול Bulk: מתי המעבר משתלם
הטעות הנפוצה ביותר היא שימוש ב-REST API רגיל לתעבורת נתונים בנפח גבוה, כי זה מה שנבנה ראשון ועובד ב-PoC. הבעיה מופיעה כשהנפח גדל: REST סופר כל בקשה (עד 200 רשומות ב-Composite) כקריאה נפרדת מול המכסה, בעוד Bulk API 2.0 מריץ אצוות של עד 10,000 רשומות ונספר בעלות נמוכה משמעותית לכל רשומה.
כלל אצבע מעשי: אם תהליך בודד מעדכן מעל כ-2,000 רשומות בהרצה אחת, המעבר ל-Bulk API כמעט תמיד משתלם - גם אם המשמעות היא לשנות את קוד הצרכן לעבוד באופן אסינכררוני עם פולינג על סטטוס ה-Job במקום תגובה מיידית. המחיר הוא Latency גבוה יותר (דקות במקום שניות), ולכן Bulk לא מתאים לתהליכים שדורשים החלטה בזמן אמת, כמו בדיקת מלאי לפני אישור הזמנה.
Backoff ו-Retry: מניעת הצפה עצמית
כשקריאת API נכשלת בגלל חסימת Limit, התגובה האינסטינקטיבית של רוב הצוותים היא לנסות שוב מיד. זו בדיוק ההתנהגות שהופכת חסימה זמנית לתקלה מתמשכת: אם עשרה תהליכים מנסים שוב באותו רגע, הם דוחפים את המערכת עמוק יותר לתוך החסימה במקום לתת לה להתאושש.
מנגנון Backoff תקין דורש שלושה מרכיבים יחד:
- Exponential Backoff - זמן ההמתנה בין ניסיונות גדל אקספוננציאלית (למשל 2, 4, 8, 16 שניות), לא נשאר קבוע.
- Jitter - תוספת אקראית קטנה לזמן ההמתנה, כדי שתהליכים מקבילים לא ינסו שוב באותה שנייה בדיוק וייצרו גל חדש של עומס.
- Circuit Breaker - אחרי מספר כשלים רצוף (למשל חמישה), התהליך מפסיק לנסות לגמרי לפרק זמן קבוע ומדווח לניטור, במקום להמשיך "לדפוק על הדלת".
בלי Circuit Breaker, תהליך שרץ כל חמש דקות וכושל בעקביות ימשיך לנסות מאה פעמים ביום ולצרוך מכסה על כשלים בלבד - זה בדיוק ההפך ממה שהמנגנון אמור למנוע. פירוט נוסף על טיפול בשגיאות ברמת האינטגרציה מופיע בניהול שגיאות אינטגרציה ב-Salesforce.
תרחיש: קמעונאות עם שלוש נקודות אינטגרציה
נניח רשת קמעונאית בינונית, כ-40 סניפים, שמפעילה Salesforce Service Cloud מול מערכת POS ומערכת ERP למלאי. שלוש אינטגרציות פעילות: סנכרון מלאי כל 15 דקות מה-ERP (כ-8,000 מק"טים), Webhook מה-POS בכל עסקה שנכשלת (כ-300 ליום), ולוח בקרה חיצוני ל-Power BI ששולף נתוני שירות כל שעה.
בחודש שבו הרשת הוסיפה תוכנית נאמנות חדשה, אינטגרציה רביעית נכנסה: בדיקת נקודות זכות בזמן אמת מול Salesforce מכל קופה, כ-6,000 קריאות ביום נוספות. תוך שבועיים, סנכרון המלאי החל להיכשל סביב 14:00-15:00, שעת השיא של הקופות. הצוות בדק תחילה את ה-ERP וחשב שהבעיה שם, אבל הלוג של Salesforce הראה REQUEST_LIMIT_EXCEEDED בדיוק בחלון הזה.
הפתרון לא היה לקנות מכסה נוספת אלא לשנות סדר עדיפויות: בדיקת נקודות הזכות עברה לשימוש ב-Platform Cache לתוצאות שלא משתנות תדיר, מה שהוריד את הקריאות בכ-70%, וסנכרון המלאי עבר מ-REST ל-Bulk API עם הרצה כל 30 דקות במקום 15. התוצאה: אותו כיסוי עסקי, צריכת מכסה נמוכה בכ-45%, ורזרבה אמיתית לצמיחה הבאה.
סיכונים ופעולות מניעה ספציפיות
| סיכון | איך הוא מתבטא בפועל | פעולת מניעה |
|---|---|---|
| אינטגרציה חדשה לא נבדקה מול תקציב קיים | חסימה מופיעה רק אחרי העלייה לייצור | דרישת סקירת קיבולת (Capacity Review) לכל אינטגרציה חדשה לפני Go Live |
| Retry ללא Backoff | חסימה זמנית הופכת לתקלה של שעות | Exponential Backoff עם Jitter ו-Circuit Breaker בכל צרכן API |
| שימוש ב-REST לנפחים גדולים | תהליך בודד צורך עשרות אחוזים מהמכסה היומית | מעבר ל-Bulk API מעל סף נפח מוגדר מראש |
| אין הפרדת Integration Users | אי אפשר לדעת איזו אינטגרציה צורכת את המכסה | Integration User ייעודי לכל מערכת חיצונית, מנוטר בנפרד |
| היעדר רזרבה בתקציב | כל תוספת קטנה דוחפת לחריגה | הקצאת 15%-20% מהמכסה כרזרבה קבועה שלא מוקצית לתהליך יומיומי |
Checklist לפני שמוסיפים אינטגרציה חדשה
- ☐ ידוע כמה אחוזים מהמכסה היומית נצרכים כרגע, לפי Integration User
- ☐ נבדק נפח שיא (לא נפח ממוצע) של האינטגרציה החדשה
- ☐ הוחלט REST מול Bulk API לפי סף נפח, לא לפי נוחות פיתוח
- ☐ קיים מנגנון Backoff עם Jitter ו-Circuit Breaker בקוד הצרכן
- ☐ הוגדרה התראה כשצריכת המכסה היומית עוברת 70%
- ☐ נבדק שימוש אפשרי ב-Platform Cache להפחתת קריאות חוזרות
- ☐ קיימת רזרבה של 15%-20% מהמכסה שלא הוקצתה מראש
- ☐ הוגדר Owner תפעולי שמקבל את ההתראה ולא רק לוג טכני
איך מנטרים את זה בשוטף
מדידה אמינה דורשת שילוב של שלושה מקורות: Event Monitoring (או Shield Event Monitoring) לצריכת API בפועל לפי משתמש, Apex Limits בקוד עצמו (Limits.getLimitApiRequests()) לבדיקה מקומית בזמן ריצה, וה-Dashboard המובנה תחת Company Information שמציג צריכה מול מכסה ברמת הארגון. אף אחד מהשלושה לא מספיק לבד: הראשון מראה מגמה, השני מונע כשל בתוך תהליך בודד, והשלישי משמש כתמונת מצב יומית לצוות התפעול.
מדד שכדאי לעקוב אחריו לאורך זמן הוא לא רק "כמה נצרך" אלא "מה קצב הגידול החודשי בצריכה" - כי זה מה שמאפשר לחזות מתי הארגון יגיע לגבול, במקום להגיב אחרי שהחסימה כבר קרתה. כאשר יש כמה מערכות תלויות אחת בשנייה, שווה לבחון גם את דפוס האינטגרציה הכולל מול חיבור Salesforce למערכות ERP, ואת שאלת המימוש - Flow מול Apex - שמשפיעה גם היא על יעילות הקריאות, בSalesforce Flow או Apex.
סיכום
Salesforce API Limits הם לא בעיה שפותרים ברגע שהיא מתגלה - הם משתנה שצריך להיות חלק מכל החלטת אינטגרציה מהיום הראשון. תקציב קריאות מתועד לפי Integration User, בחירה מודעת בין REST ל-Bulk לפי נפח, ומנגנון Backoff שמונע הצפה עצמית - שלושת אלה יחד הם מה שמבדיל בין ארגון שמגלה את הבעיה כשהוא כבר חסום, לבין ארגון שרואה אותה מתקרבת חודש מראש ופועל בזמן.
