תארו לעצמכם: צוות הפרונטאנד שלכם מבלה שעות בתיאום עם מהנדסי הבקאנד כדי להרכיב עמוד אחד. כל מיקרוסרוויס מחזיר נתונים בפורמט משלו — אתם צריכים לבצע 5–10 בקשות ל-API שונים. נוצרות בעיות N+1, זמן האחזור גדל, והקאשינג הופך לכאב ראש. בפרויקט אחד, צמצמנו את מספר הבקשות מ-12 ל-2 (הפחתה של 83%) על ידי הטמעת GraphQL Federation. הניסיון שלנו — 7+ שנים במערכות מבוזרות, מעל 50 פריסות GraphQL בייצור. Federation הוא לא רק שער (gateway) אלא גישה דקלרטיבית: כל צוות מתאר כיצד המיקרוסרוויס שלו מרחיב את גרף הנתונים המשותף. בניגוד לאגרגציה ידנית, Federation בונה אוטומטית תוכנית ביצוע אופטימלית באמצעות @key ו-@requires.
איך למזג מיקרוסרוויסים עם GraphQL Federation?
Federation מאפשר לשלב מספר שירותי GraphQL עצמאיים (subgraphs) ל-API אחד. הלקוח שולח בקשה אחת ל-Federation Gateway (Apollo Router), שאוסף נתונים מ-subgraphs שונים ומחזיר תשובה מאוחדת. כל צוות מחזיק ב-subgraph משלו ופורס אותו באופן עצמאי — ללא חסימות או אישורים. מפרט Apollo Federation מתאר את כל פרטי הפרוטוקול.
ארכיטקטורת Federation:
- לקוח (דפדפן/מובייל) → Federation Gateway (Apollo Router / Apollo Gateway)
- User Subgraph (Node.js) → Postgres
- Order Subgraph (Go) → Postgres
- Product Subgraph (Python) → MongoDB
- Review Subgraph (Node.js) → Postgres
Subgraph: שירות User — דוגמת הטמעה
// user-service/schema.ts import { buildSubgraphSchema } from '@apollo/subgraph'; import { gql } from 'graphql-tag'; const typeDefs = gql` extend schema @link(url: "https://specs.apollo.dev/federation/v2.3", import: ["@key", "@shareable"]) type User @key(fields: "id") { id: ID! name: String! email: String! createdAt: DateTime! } type Query { me: User user(id: ID!): User } `; const resolvers = { User: { __resolveReference: async ({ id }) => { return userRepository.findById(id); } }, Query: { me: (_, __, { userId }) => userRepository.findById(userId), user: (_, { id }) => userRepository.findById(id) } }; export const schema = buildSubgraphSchema({ typeDefs, resolvers });Subgraph: שירות Order — הרחבת טיפוס
// order-service/schema.ts const typeDefs = gql` extend schema @link(url: "https://specs.apollo.dev/federation/v2.3", import: ["@key", "@external", "@requires"]) type Order @key(fields: "id") { id: ID! status: OrderStatus! total: Float! items: [OrderItem!]! customer: User! createdAt: DateTime! } type User @key(fields: "id") { id: ID! @external orders(limit: Int = 10): [Order!]! orderStats: OrderStats! } type OrderStats { totalOrders: Int! totalSpent: Float! lastOrderAt: DateTime } enum OrderStatus { PENDING PAID SHIPPED DELIVERED CANCELLED } type Query { order(id: ID!): Order orders(customerId: ID, status: OrderStatus): [Order!]! } `; const resolvers = { User: { __resolveReference: async ({ id }) => ({ id }), orders: async ({ id }, { limit }) => orderRepository.findByCustomerId(id, limit), orderStats: async ({ id }) => orderRepository.getStatsForCustomer(id) }, Order: { __resolveReference: async ({ id }) => orderRepository.findById(id), customer: ({ customerId }) => ({ __typename: 'User', id: customerId }) } };Apollo Router (Federation Gateway) — קונפיגורציה
--- # router.yaml federation_version: 2.3 supergraph: listen: 0.0.0.0:4000 subgraphs: users: routing_url: http://user-service:4001/graphql orders: routing_url: http://order-service:4002/graphql products: routing_url: http://product-service:4003/graphql cors: origins: - https://app.example.com headers: all: request: - propagate: named: Authorization - propagate: named: X-Correlation-Id ---הרצה דרך Docker:
// user-service/schema.ts import { buildSubgraphSchema } from '@apollo/subgraph'; import { gql } from 'graphql-tag'; const typeDefs = gql` extend schema @link(url: "https://specs.apollo.dev/federation/v2.3", import: ["@key", "@shareable"]) type User @key(fields: "id") { id: ID! name: String! email: String! createdAt: DateTime! } type Query { me: User user(id: ID!): User } `; const resolvers = { User: { __resolveReference: async ({ id }) => { return userRepository.findById(id); } }, Query: { me: (_, __, { userId }) => userRepository.findById(userId), user: (_, { id }) => userRepository.findById(id) } }; export const schema = buildSubgraphSchema({ typeDefs, resolvers });.Federation לעומת REST לעומת Gateway רגיל
Federation מהיר פי 3 מאגרגטור REST בזכות שליפה מקבילה וקאשינג ברמת ה-subgraph. בפרויקט אחד, צמצמנו את זמן טעינת העמוד מ-2.3 שניות ל-0.8 שניות — שיפור של 65%. הטבלה שלהלן מציגה את ההבדלים המרכזיים:
מאפיין Federation אגרגטור REST Gateway רגיל מספר בקשות 1 5–10 1 (אבל נתונים נשלפים ברצף) זמן תגובה ~50 אלפיות שנייה (בקשות מקבילות) ~200 אלפיות שנייה ~100–150 אלפיות שנייה (ברצף) עצמאות צוות ✅ כל צוות מחזיק ב-subgraph משלו ❌ קוד משותף ❌ קוד משותף שינויי סכמה ללא חסימות דורש תיאום דורש תיאום קאשינג ברמת ה-subgraph מטמון HTTP ריכוזי כלי מטרה הפצה Apollo Router Federation Gateway, איסוף נתונים מקביל קוד פתוח + Managed Apollo Rover CLI פרסום סכמה ואימות קוד פתוח Apollo Studio רישום סכמות, ניטור SaaS Managed Federation (Apollo Studio)
עם Managed Federation, סכמות ה-subgraph מתפרסמות ל-Apollo Studio Registry. ה-Router טוען אוטומטית את סכמת ה-supergraph העדכנית ביותר כאשר כל subgraph משתנה. פרסום עם בדיקות תאימות מתבצע דרך
// order-service/schema.ts const typeDefs = gql` extend schema @link(url: "https://specs.apollo.dev/federation/v2.3", import: ["@key", "@external", "@requires"]) type Order @key(fields: "id") { id: ID! status: OrderStatus! total: Float! items: [OrderItem!]! customer: User! createdAt: DateTime! } type User @key(fields: "id") { id: ID! @external orders(limit: Int = 10): [Order!]! orderStats: OrderStats! } type OrderStats { totalOrders: Int! totalSpent: Float! lastOrderAt: DateTime } enum OrderStatus { PENDING PAID SHIPPED DELIVERED CANCELLED } type Query { order(id: ID!): Order orders(customerId: ID, status: OrderStatus): [Order!]! } `; const resolvers = { User: { __resolveReference: async ({ id }) => ({ id }), orders: async ({ id }, { limit }) => orderRepository.findByCustomerId(id, limit), orderStats: async ({ id }) => orderRepository.getStatsForCustomer(id) }, Order: { __resolveReference: async ({ id }) => orderRepository.findById(id), customer: ({ customerId }) => ({ __typename: 'User', id: customerId }) } };.# В CI/CD пайплайне rover subgraph publish my-graph@production \ --schema ./schema.graphql \ --name orders \ --routing-url http://order-service:4002/graphqlהרשאות ברמת ה-subgraph
כל subgraph מאמת הרשאות באופן עצמאי. דוגמה ב-TypeScript: ב-resolver של Order
# router.yaml federation_version: 2.3 supergraph: listen: 0.0.0.0:4000 subgraphs: users: routing_url: http://user-service:4001/graphql orders: routing_url: http://order-service:4002/graphql products: routing_url: http://product-service:4003/graphql cors: origins: - https://app.example.com headers: all: request: - propagate: named: Authorization - propagate: named: X-Correlation-Id, ודאו שהמשתמש הנוכחי הוא בעל ההזמנה או בעל תפקיד אדמין. במקרה של כישלון, החזירוdocker run -p 4000:4000 -v $(pwd)/router.yaml:/dist/config/router.yaml -e APOLLO_KEY=service:my-graph:xxx -e APOLLO_GRAPH_REF=my-graph@production ghcr.io/apollographql/router:latest.למה לבחור ב-Federation לפרויקט חדש?
Federation מספק עצמאות צוותית, פריסות אטומיות ובדיקות תאימות אוטומטיות. אנו מבטיחים שהסכמה תישאר עקבית עם כל שינוי. זהו הפתרון הטוב ביותר עבור חברות עם 3+ מיקרוסרוויסים שבהן מהירות השינוי היא קריטית. לצוות שלנו יש 7+ שנות ניסיון ומעל 50 פריסות GraphQL מוצלחות.
מה כלול בעבודה?
- בדיקת ארכיטקטורה קיימת והגדרת גבולות ה-subgraph.
- עיצוב סכמת supergraph עם @key ו-@requires.
- הטמעת שירותי subgraph (Node.js, Go, Python — כל טכנולוגיה).
- קונפיגורציה של Apollo Router עם CORS, הרשאות, ניטור.
- שילוב Managed Federation עם צינור בדיקות תאימות ב-CI.
- תיעוד סכמה ונקודות הרחבה.
- הדרכת צוות על Federation.
- תמיכה לאחר השקה: שבועיים לאחר העלייה לאוויר.
תהליך ולוחות זמנים
- ניתוח — זיהוי גבולות subgraph, הגדרת נקודות אינטגרציה עם מערכות legacy.
- עיצוב — תיאור סכמת supergraph, הסכמה על @key ו-@requires.
- פיתוח — כל subgraph נוצר כשירות נפרד עם פריסה משלו.
- קונפיגורציית Router — הגדרת CORS, הרשאות, ניטור (Apollo Studio).
- Managed Federation — שילוב צינור CI עם בדיקות תאימות.
- בדיקות — בדיקות עומס ובדיקות E2E.
- השקה — פריסה מדורגת עם ניטור שגיאות.
לוחות זמנים:
- 2–3 subgraphs עם Federation בסיסי — 2–3 שבועות.
- Apollo Router + Managed Federation + בדיקות CI — שבוע נוסף.
- @requires, @provides מורכבים, resolvers מקוננים — 1–2 שבועות נוספים.
המחיר מתחיל מ-$5,000 עבור הגדרת Federation בסיסית (2–3 subgraphs). קבלו ייעוץ — נבחן את הפרויקט שלכם ונספק הצעת מחיר מדויקת.
דוגמה להטמעת subgraph מפורטת ב-TypeScript
הקוד המלא עבור User ו-Order subgraphs זמין במאגר. נוכל להתאים אותו לטכנולוגיה שלכם אם נדרש.







