Представьте: фронтенд-команда тратит часы на координацию с бэкендерами, чтобы собрать одну страницу. Каждый микросервис отдаёт данные в своём формате — приходится делать 5–10 запросов к разным API. Возникают N+1 проблемы, latency растёт, кэширование превращается в головную боль. На одном из проектов мы сократили количество запросов с 12 до 2, внедрив Federation. Наш опыт — 7+ лет в распределённых системах, более 50 продакшен-внедрений GraphQL. Федерация — это не просто gateway, а декларативный подход: каждая команда описывает, как её микросервис расширяет общий граф данных. В отличие от ручного агрегирования, Federation автоматически строит оптимальный план выполнения, используя @key и @requires.
Как объединить микросервисы с помощью GraphQL Federation?
Federation позволяет объединить несколько независимых GraphQL-сервисов (subgraph) в единый API. Клиент делает один запрос к Federation Gateway (Apollo Router), который собирает данные из разных subgraph и возвращает единый ответ. Каждая команда владеет своим subgraph и деплоит его независимо — без блокировок и согласований. Apollo Federation specification описывает все детали протокола.
Архитектура 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 Service — пример реализации
// 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 Service — расширение типов
// 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: 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 по сравнению с REST и обычным Gateway?
| Характеристика | Federation | REST-агрегатор | Обычный Gateway |
|---|---|---|---|
| Количество запросов | 1 | 5–10 | 1 (но данные собираются последовательно) |
| Время ответа | ~50 мс (параллельные запросы) | ~200 мс | ~100–150 мс (последовательно) |
| Независимость команд | ✅ Каждая команда владеет subgraph | ❌ Общая кодовая база | ❌ Общая кодовая база |
| Изменение схемы | Без блокировок | Согласование | Согласование |
| Кэширование | На уровне subgraph | HTTP-кэш | Централизованное |
Federation позволяет повысить производительность в 2–3 раза по сравнению с REST-агрегатором за счёт параллельной выборки и кэширования на уровне subgraph. На одном проекте мы снизили время загрузки страницы с 2.3 до 0.8 секунды.
| Инструмент | Назначение | Распространение |
|---|---|---|
| Apollo Router | Federation Gateway, параллельный сбор данных | Open source + Managed Apollo |
| Rover CLI | Публикация и проверка схем | Open source |
| Apollo Studio | Реестр схем, мониторинг | SaaS |
Managed Federation (Apollo Studio)
При Managed Federation схемы subgraph публикуются в Apollo Studio Registry. Router загружает актуальную supergraph-схему автоматически при изменении любого subgraph. Публикация с проверкой совместимости выполняется через rover subgraph check.
# В CI/CD пайплайне
rover subgraph publish my-graph@production \
--schema ./schema.graphql \
--name orders \
--routing-url http://order-service:4002/graphql
Авторизация на уровне subgraph
Каждый subgraph самостоятельно проверяет права. Пример на TypeScript: в ресолвере Order __resolveReference проверяется, что текущий пользователь — владелец заказа или имеет роль admin. В случае отказа возвращается ошибка ForbiddenError.
Почему Federation стоит выбрать для нового проекта?
Federation даёт независимость командам, атомарные деплои и автоматическую проверку совместимости. Мы гарантируем, что схема останется консистентной при каждом изменении. Это лучшее решение для компаний с 3+ микросервисами, где важна скорость изменений.
Что входит в работу?
- Аудит текущей архитектуры и выделение границ subgraph.
- Проектирование supergraph-схемы с @key и @requires.
- Реализация subgraph-сервисов (Node.js, Go, Python — любой стек).
- Настройка Apollo Router с CORS, авторизацией, мониторингом.
- Интеграция Managed Federation с CI-пайплайном проверки совместимости.
- Документация по схеме и точкам расширения.
- Обучение команды работе с Federation.
- Поддержка на старте: 2 недели после запуска.
Процесс работы и сроки
- Анализ — выделяем границы subgraph, определяем точки интеграции с legacy.
- Проектирование — описываем supergraph-схему, согласуем @key и @requires.
- Разработка — каждый subgraph создаётся как отдельный сервис с собственным деплоем.
- Настройка Router — конфигурация CORS, авторизации, мониторинга (Apollo Studio).
- Managed Federation — подключаем CI-пайплайн с проверкой совместимости.
- Тестирование — нагрузочное тестирование и E2E-тесты.
- Запуск — пошаговый rollout с мониторингом ошибок.
Сроки реализации:
- 2–3 subgraph с базовой Federation — 2–3 недели.
- Apollo Router + Managed Federation + CI-проверки совместимости — ещё 1 неделя.
- Сложные @requires, @provides, nested resolvers — 1–2 дополнительные недели.
Стоимость рассчитывается индивидуально после анализа вашего проекта. Получите консультацию — мы оценим объём работы и предложим оптимальное решение. Закажите внедрение Federation: свяжитесь с нами — подготовим предложение под ключ. Ваша архитектура станет гибкой и масштабируемой без лишних затрат.
Пример детальной реализации subgraph на TypeScript
Весь код User и Order subgraph доступен в репозитории. При необходимости адаптируем под ваш стек.Получите консультацию по внедрению Federation — напишите нам, и мы оценим ваш проект.







