פיתוח API עם REST, GraphQL, WebSocket ו-tRPC
לקוח מגיע אלינו עם קולקציית Postman של 200 אנדפוינטים ואומר: "הכול עובד, אבל הפרונטאנד איטי." אנחנו פותחים את לשונית ה-Network — 47 בקשות עוקבות לטעינת דף דשבורד אחד. כל אחת מחכה לקודמתה. זו לא בעיית מהירות שרת — זו בעיית ארכיטקטורת API. עם 10 שנות ניסיון בשוק, עיצבנו מחדש עשרות אינטגרציות כאלה, ואנחנו מבטיחים: הפרוטוקול והחוזה הנכונים פותרים את הבעיה מהשורש.
מתי REST מפסיק להספיק
REST עובד היטב עבור פעולות CRUD פשוטות. אבל ברגע שמופיעה אפליקציית מובייל לצד הממשק האינטרנטי, מתחיל over-fetching: אפליקציית המובייל מבקשת /api/users/123 ומקבלת אובייקט של 4KB, אבל צריכה רק name ו-avatar. תכפילו זאת ברשימה של 50 משתמשים — 200KB תעבורה במקום 8KB.
GraphQL פותר זאת עם ערכות בחירה (selection sets). הלקוח מתאר בדיוק את השדות שהוא צריך, והשרת מחזיר רק אותם. בפרויקט עם React Native + Next.js, העברנו מ-REST ל-Apollo Server: גודל ה-payload במסך הראשי ירד מ-340KB ל-28KB — חיסכון של 92% בתעבורה. המהנדסים המוסמכים שלנו מאשרים: הכאב האופייני באימוץ GraphQL הוא שאילתת N+1. רזולבר לשדה author בפוסט קורא ל-SELECT * FROM users WHERE id = ? עבור כל פוסט ברשימה. בעמוד עם 20 פוסטים — 21 שאילתות מסד נתונים. נפתר עם DataLoader — הוא מאגד שאילתות והופך אותן לאחת SELECT * FROM users WHERE id IN (...).
מה זה tRPC ובמה הוא טוב יותר מ-REST/GraphQL?
אם כל הסטACK הוא TypeScript (Next.js + Node/Bun), tRPC מסיר שכבה שלמה של בעיות. אתה מגדיר פרוצדורה בשרת — הלקוח מקבל type-safety מלא אוטומטית, ללא יצירת קוד וללא Swagger. שינית שם שדה ב-Zod schema — TypeScript מדגיש את כל המקומות בפרונטאנד שבהם הוא בשימוש. tRPC מקטין קוד פי 2 בהשוואה ל-REST + Swagger + openapi-typescript: אין צורך לתחזק מפרט נפרד וליצור טיפוסים — הכול נגזר מ-runtime validators. עם זאת, tRPC אינו מתאים אם ה-API נצרך על ידי לקוחות צד שלישי או אפליקציות מובייל בשפות אחרות — במקרים כאלה אנו משתמשים ב-GraphQL או REST עם מפרט OpenAPI.
WebSocket ו-real-time: מתי SSE, מתי WS?
סקירת HTTP כל 5 שניות היא אשליה של real-time עם עיכוב של עד 5 שניות ועומס מיותר על השרת. לצ'אטים, התראות חיות, עריכה שיתופית — WebSocket או Server-Sent Events. SSE הוא זרם חד-כיווני מהשרת ללקוח, עובד על HTTP רגיל, ומתחבר מחדש אוטומטית. מתאים להתראות, סטרימינג של נתונים, פסי התקדמות. WebSocket הוא דו-כיווני, נחוץ לצ'אטים ותכונות שיתופיות. הניסיון מראה: 80% ממשימות ה-'real-time' נפתרות עם SSE, לא WebSocket — פחות מורכבויות תשתית.
טעות אופיינית: פתיחת חיבור WebSocket עבור כל קומפוננטת עמוד. בפרויקט אחד, הדשבורד פתח 12 חיבורי WS מקבילים. הגישה הנכונה היא מנהל חיבור אחד ברמת האפליקציה, ומנויים דרכו. בתוצאות העבודה שלנו, אנחנו תמיד מעבירים את סכימת החיבור ופתרון מוכן.
| פרוטוקול | טיפוסים | Over-fetching | גרסאות | Real-time |
|---|---|---|---|---|
| REST | חלש (OpenAPI) | כן | URL / Header | סקירה (Polling) |
| GraphQL | חזק (SDL) | לא | Deprecation | Subscriptions |
| tRPC | מלא (TypeScript) | לא | בדיקות TypeScript | Subscriptions (אופציונלי) |
Swagger / OpenAPI כחוזה
תיעוד שנכתב בדיעבד הופך למיושן יום אחרי השחרור. אנחנו כותבים את מפרט OpenAPI 3.1 לפני תחילת הפיתוח; הוא הופך לחוזה בין הפרונטאנד לבאקאנד. הפרונטאנד מייצר טיפוסים דרך openapi-typescript, הבאקאנד מאמת נתונים נכנסים באמצעות סכמות שנוצרו. סטייה מהחוזה ביישום נתפסת ב-CI, לא בסקירת קוד. עבור Laravel — l5-swagger או dedoc/scramble. עבור Node.js — @fastify/swagger או Zod + zod-to-openapi.
כיצד לאמת כראוי API?
JWT עם access tokens ארוכי טווח ללא רוטציה הוא מקור לבעיות בעת פשרה. הסכימה הנכונה: access token ל-15 דקות, refresh token ל-30 יום עם רוטציה בכל שימוש. ה-refresh token מאוחסן ב-httpOnly cookie, ה-access token בזיכרון (לא ב-localStorage). לתקשורת בין-שירותית — API Keys עם הגבלות scope או mTLS. OAuth 2.0 עם PKCE עבור לקוחות ציבוריים (SPA, מובייל).
כיצד לטפל בגרסאות ותאימות לאחור?
שינויים שוברים ב-API ללא גרסאות שוברים לקוחות. שלוש גישות בהן אנו משתמשים בפרויקטים:
| שיטה | דוגמה | מתי להשתמש |
|---|---|---|
| גרסאות ב-URL | /api/v2/ |
REST API עם תמיכה ארוכת טווח ב-legacy |
| גרסאות ב-Header | Accept: application/vnd.api+json;version=2 |
שינויי URL מינימליים |
| אבולוציוני (Deprecation) | הוספת שדות, הוראת deprecated ב-GraphQL | עבור GraphQL — הסרה חלקה של שדות |
אנחנו מבטיחים תאימות לאחור באמצעות בדיקות אוטומטיות (oasdiff) ב-CI.
כיצד אנו מפתחים APIs: תוכנית שלב אחר שלב
- ניתוח — ביקורת על אינטגרציות קיימות, בניית סכמת נתונים, בחירת פרוטוקול (REST/GraphQL/tRPC/WebSocket).
- עיצוב חוזה — OpenAPI או SDL (GraphQL) לפני השורה הראשונה של הקוד.
- פיתוח — יישום לפי החוזה, בדיקות יחידה לכל אנדפוינט.
- בדיקות עומס — k6: 500 משתמשים וירטואליים, 10 דקות, p95 latency ≤ 200ms.
- פריסה — CI/CD עם בדיקת תאימות לאחור, פרסום תיעוד אוטומטי.
- הדרכת צוות — העברת קולקציית Postman או Playground, הוראות חיבור.
טעויות אופייניות שאנו מבטלים
- N+1 בשאילתות ללא DataLoader.
- חוסר rate limiting — DDOS דרך אנדפוינטים לא מאומתים.
- אחסון access token ב-localStorage.
- פתיחת חיבורי WebSocket מרובים במקום מנהל חיבור יחיד.
- תיעוד שלא עודכן לאחר השחרור.
מה כלול (תוצרים)
- מפרט OpenAPI 3.1 (או SDL עבור GraphQL).
- טיפוסי לקוח שנוצרו עבור TypeScript / Dart / Kotlin.
- מערך בדיקות אוטומטיות המכסות את כל האנדפוינטים (יחידה + אינטגרציה).
- בדיקות עומס (k6) ודוח (p50/p95/p99 latency, RPS).
- תיעוד ב-Swagger UI / Redoc / GraphiQL.
- הדרכת צוות (סדנה של 2–4 שעות).
- תמיכה ל-30 יום לאחר המסירה (לפי החוזה).
הניסיון שלנו
- 10+ שנים בשוק פיתוח ה-API.
- 200+ פרויקטים שהושלמו (REST, GraphQL, WebSocket, tRPC).
- 50+ מהנדסים מוסמכים (AWS, Kubernetes, API Design).
- חיסכון ממוצע בתעבורה של 85% במעבר מ-REST ל-GraphQL עבור אפליקציות מובייל.
- 100% תאימות לאחור — לא לקוח שבור אחד בשלוש השנים האחרונות.
לוח זמנים
פיתוח API עבור פרויקט SaaS טיפוסי עם 30–50 אנדפוינטים: בין 3 ל-8 שבועות בהתאם למורכבות הלוגיקה העסקית ומספר האינטגרציות החיצוניות. העברת REST API קיים ל-GraphQL: בין 2 ל-6 שבועות. הוספת שכבת WebSocket לבאקאנד קיים: בין 1 ל-3 שבועות. העלות מחושבת באופן אישי לאחר ביקורת. קבלו ייעוץ — צרו קשר כדי לדון בפרויקט שלכם.







