REST, GraphQL, gRPC: когда что выбрать
Тройка REST, GraphQL и gRPC — не «лучший» против «худшего», а три разных набора компромиссов. Зрелая команда часто использует все три одновременно: REST смотрит наружу, GraphQL агрегирует для UI, gRPC общается между сервисами. В этом уроке — таблица для сравнения, decision tree и реальные паттерны.
Сравнительная таблица по 12 критериям
| Критерий | REST | GraphQL | gRPC |
|---|---|---|---|
| Формат payload | JSON (чаще), XML, MessagePack | JSON | Protobuf (бинарный), опционально JSON |
| Транспорт | HTTP/1.1, HTTP/2, HTTP/3 | HTTP/1.1+; WebSocket для subscriptions | Только HTTP/2 (HTTP/3 — экспериментально) |
| Schema-first | Опционально (OpenAPI) | Обязательно (SDL) | Обязательно (.proto) |
| Типизация | Слабая по умолчанию, через OpenAPI — сильная | Сильная (schema валидируется runtime) | Сильная (compile-time через codegen) |
| Размер payload | Базовая линия (1x) | 0.7-1x от REST | 0.1-0.3x от REST |
| Latency на 1 RPC | Низкая (HTTP/2 + JSON ~5ms) | Низкая, но overhead парсинга AST | Самая низкая (бинарный + HTTP/2) |
| Browser support | Полный, нативно | Полный (через POST или GET) | Частичный, нужен gRPC-Web |
| Tooling/debug | curl, Postman, браузер DevTools | GraphiQL, Apollo Studio, codegen | grpcurl, BloomRPC, Wireshark |
| Кривая обучения | Низкая | Средняя (resolvers, N+1, fragments) | Средняя-высокая (proto, codegen, HTTP/2) |
| HTTP-кэширование | Из коробки (GET + ETag/Cache-Control) | Сложное — всё POST, нужен app-level cache | Нет нативной поддержки |
| Streaming | SSE (server-only), отдельный WebSocket | Subscriptions через WebSocket/SSE | Нативно: server/client/bidi |
| Use case | Public API, integrations, CRUD | BFF, mobile, разнообразные клиенты | Internal microservices, ML, observability |
Каждая ячейка — упрощение, но даёт ощущение порядка величин. Размер payload-а особенно показателен: на типичном сообщении в 200 полей gRPC даст 1-3 KB, REST/JSON — 8-15 KB, GraphQL подберёт что-то посередине благодаря фильтрации полей.
HTTP/3 и QUIC: следующее поколение транспортаDecision tree
Где живут клиенты?
Старт: появилась задача спроектировать API между двумя системамиREST + OpenAPI 3.1
Партнёры ожидают REST OpenAPI с примерами в curl, Postman и привычными статус-кодамиКто потребитель?
Внутренние микросервисы -- выбор зависит от того, кто конечный потребитель: backend или браузерSPA / Mobile UI
Браузерный SPA или мобильное приложение с разными экранами и переменчивыми требованиямиService-to-service
Высокий QPS, минимальная latency, оба конца под нашим контролемПростой CRUD
Простые CRUD сервисы с маленькой командой и без сильной нагрузкиDecision tree не строгий закон, а отправная точка. В реальности добавляются ещё измерения: совместимость с существующим стеком (если уже есть Apollo Federation — расширять её дешевле), требования compliance, навыки команды.
Гибридные архитектуры
Большинство production-систем используют все три парадигмы одновременно. Типовая раскладка:
[ Внешние клиенты, партнёры ]
|
REST + OpenAPI
|
+--------------+
| API Gateway |
+--------------+
|
GraphQL BFF
|
+-------------------+-------------------+
| | |
gRPC gRPC gRPC
| | |
[Order svc] [Catalog svc] [User svc]
| | |
gRPC gRPC gRPC
| | |
[ML inference] [Search index] [Auth provider]
Каждый слой подобран под свой сценарий:
- REST наружу — стабильный контракт, OpenAPI-документация, кэширование на CDN, дружба с CORS.
- GraphQL для UI — мобильный и веб-фронт получают ровно те данные, что нужны конкретному экрану. BFF агрегирует ответы от микросервисов.
- gRPC внутри — низкая latency, типизированные контракты, streaming для аналитики и ML.
В DE-сценариях встречается другая раскладка: REST для внешних SaaS-источников (Stripe, Salesforce), GraphQL для админских dashboard-ов (Hasura поверх Postgres), gRPC для внутренней передачи метрик и моделей.
SaaS источник (REST)
Salesforce REST API: GET /sobjects/Account?since=2026-05-14Ingest worker
Airflow DAG, Python ingest taskStream platform (Kafka)
Запись в Kafka, метрики в Prometheus через OTLP gRPCOTel Collector
OpenTelemetry Collector принимает spans/metrics через gRPCАналитический storage
ClickHouse, S3 + Parquet, SnowflakeДашборд (GraphQL)
Hasura или Apollo BFF поверх Postgres metadata + ClickHouse аналитикиАнтипаттерны
Опытным взглядом видны типовые ошибки выбора протокола.
GraphQL для классического CRUD
Сервис из 5 endpoint-ов, два из которых GET-list и GET-by-id, один POST-create, один PUT-update, один DELETE. Команда внедряет GraphQL — и получает overhead в виде schema, codegen, N+1 риска и потери HTTP-кэширования. REST с OpenAPI решит ту же задачу в 3 раза меньшим объёмом кода.
gRPC через интернет наружу
Предложить публичной интеграции gRPC означает: партнёрам нужен HTTP/2-совместимый клиент, gRPC-кодген на их языке, проблемы с корпоративными прокси, отсутствие удобного браузерного debugger-а. Большинство партнёров просто откажется. gRPC живёт внутри организации; на границе ставят REST или GraphQL gateway.
REST с глубокой вложенностью для мобильных
API, требующее 8 запросов на отрисовку одного экрана и возвращающее 30 полей вместо нужных 4, — типичный сигнал, что пора рассмотреть GraphQL BFF. На медленной мобильной сети каждый round trip ощутим.
Schema-first без дисциплины
Проект на gRPC, в котором .proto файлы хранятся в монорепе, но никто не следит за breaking changes. Через год — десятки конфликтов tag-ов, удалённых полей и сломанных клиентов. Решение: автоматический lint (buf для proto), policy против изменения tag-ов, контракт-тесты.
GraphQL без ratelimit-а и query complexity
Открытый GraphQL endpoint, на котором клиент может прислать запрос с глубиной вложенности 50 и cartesian product через repeated. Сервер положит БД одним запросом. Защита: лимит глубины, лимит сложности (graphql-cost-analysis), persisted queries (только заранее одобренные тексты), rate limit per token.
Самая частая ошибка — выбирать протокол по моде, а не по требованиям. «У нас же микросервисы, давайте gRPC» без анализа QPS и команды приводит к месяцам потерянной продуктивности. Выбирайте под конкретные ограничения: latency, тип клиентов, объём команды, навыки.
Реальные примеры компаний
- Netflix. GraphQL Federation как BFF для всех экранов (TV, mobile, web). Под капотом — REST и gRPC сервисы, GraphQL слой агрегирует. Доклад «How Netflix Scales its API with GraphQL Federation» — обязателен к просмотру.
- Shopify. Storefront API — GraphQL для headless commerce. Admin API в 2026 уже на 90% переехал с REST на GraphQL, REST остался как deprecated fallback.
- GitHub. REST API v3 + GraphQL API v4 параллельно. Новые фичи доступны раньше через GraphQL. Webhooks для событий.
- Stripe. REST + Webhooks как фундамент. Никакого GraphQL — стабильность контракта дороже гибкости.
- Google. gRPC внутри (его и придумали). Снаружи — REST через
transcoding, который автоматически генерирует REST-обёртку из.proto. - Uber. gRPC + Protobuf для service-to-service (десятки тысяч сервисов). REST на edge, GraphQL для мобильного rider/driver приложения.
- Apollo (Apollo Studio). Сами на себе: GraphQL Federation для собственного API, REST в редких случаях для legacy.
Эволюция со временем
Большинство компаний начинают с REST, потому что он простой и весь мир его понимает. По мере роста:
- Появляется второй клиент (мобильное приложение). REST с overfetching становится узким местом — добавляется GraphQL BFF.
- Микросервисы множатся, latency между ними растёт. Внутренняя коммуникация переезжает на gRPC.
- Real-time сценарии (notifications, чаты, телеметрия) — добавляются gRPC streaming или WebSocket.
- Public API остаётся REST — потому что партнёрам так удобно, и менять контракт уже дорого.
Это эволюционный путь, а не революция. Ни одна крупная компания не переводит всё на один протокол — это нерентабельно и ломает экосистему интеграций.
Memo для junior DE
Что нужно знать практически:
- Чтение OpenAPI и
.proto— обязательный навык. Если в команде уже есть Apollo Federation — добавить туда тип Python data sources. - Уметь сделать выгрузку через REST (httpx) и GraphQL (httpx + POST с query). Уметь сгенерировать gRPC stub из
.proto. - Понимать стоимость: сколько RPS выдержит endpoint, какова latency, есть ли batch-endpoint.
- Различать сценарии: внешний источник = почти всегда REST/GraphQL; внутренние сервисы — gRPC или REST в зависимости от компании.