В 2018 GraphQL преподносили как «убийцу REST». В 2026 — это просто один из инструментов, и для большинства новых проектов выбор не очевиден. Разбираем, что и когда разумно.
Краткий ответ
| Сценарий | Выбор |
|---|---|
| Один фронтенд на React + один бэкенд | tRPC или REST |
| Несколько клиентов (web + iOS + Android) | GraphQL |
| Много вложенных связей в данных | GraphQL |
| Простой CRUD с CRUD-операциями | REST |
| Публичное API для сторонних разработчиков | REST + OpenAPI |
| Микросервисы с разными командами | REST или gRPC |
| Внутренний админ-инструмент | REST или server actions |
Что не так с REST в 2026
REST никуда не делся, но в спецификации много свободы — каждая команда городит свой стиль. Типичные жалобы:
- Underfetching: чтобы показать карточку пользователя с заказами, нужно
GET /user/42+GET /user/42/orders— два запроса. - Overfetching:
/products/42возвращает 30 полей, а вам нужно 3. - Версионирование:
/v2/productsломает совместимость, поддерживать несколько версий — головная боль. - Документация: OpenAPI помогает, но писать его никто не хочет.
Что предлагает GraphQL
Один эндпоинт, клиент сам выбирает поля и связи:
query {
user(id: 42) {
name
email
orders(limit: 5) {
id
total
items { name price }
}
}
}
Сервер вернёт ровно это, ни больше ни меньше. Никаких лишних запросов и полей.
// типизация на клиенте через codegen
const { data } = useUserOrdersQuery({ variables: { id: 42 } });
// data.user.orders[0].items[0].name — TypeScript всё знает
Это правда удобно, особенно когда фронтенд активно меняется.
Что в нём болит
- N+1 проблема: запрос
users { orders }без DataLoader-а делает запрос в БД на каждого юзера. Решается, но ловушка постоянная. - Кеширование: в REST — HTTP
Cache-Controlбесплатно. В GraphQL — каждый запрос POST с уникальным телом, плохо кешируется в HTTP. Нужен Apollo Client cache на клиенте, persisted queries для CDN. - Сложность сервера: schema, resolvers, subscriptions, federation — порог входа выше.
- Безопасность: легко допустить query, который повесит БД (deep query). Нужны depth limits, query cost analysis.
- Мониторинг: один эндпоинт — все метрики идут на /graphql, нужны теги операций.
tRPC — третий вариант
Для проектов, где фронт и бэк на TypeScript и в одной кодовой базе, tRPC — часто лучший выбор. Нет ни схемы GraphQL, ни OpenAPI — типы шарятся напрямую.
// server
export const appRouter = router({
getUser: publicProcedure
.input(z.object({ id: z.number() }))
.query(async ({ input }) => db.user.findUnique({ where: { id: input.id } })),
});
export type AppRouter = typeof appRouter;
// client
const user = await trpc.getUser.query({ id: 42 });
// полная типизация, автокомплит
Без codegen, без отдельной схемы, без рантайм-проверок схемы. Всё типизировано через TypeScript-вывод.
Минусы tRPC:
- Только для TS-стека, нет интеграции с Android/iOS.
- Нет публичного API-договора.
- Жёсткая связь фронт-бэк по версии.
Server Actions — ещё проще
В Next.js 15 для многих случаев вообще не нужен ни REST, ни GraphQL, ни tRPC:
"use server";
export async function getUser(id: number) {
return db.user.findUnique({ where: { id } });
}
const user = await getUser(42);
Полная типизация, нулевой бойлерплейт. Подходит для внутренних инструментов и SSR-приложений на Next.js. Не подходит, когда есть отдельные клиенты.
Сравнение
| Критерий | REST | GraphQL | tRPC | Server Actions |
|---|---|---|---|---|
| Типизация | OpenAPI + codegen | schema + codegen | TypeScript inference | TypeScript inference |
| Над/недоборка данных | проблема | решено | по запросу | по запросу |
| HTTP-кеширование | топ | плохо | плохо | плохо |
| Кросс-язык клиенты | да | да | нет (только TS) | нет |
| Скорость разработки | средне | медленно (схема) | быстро | очень быстро |
| Порог входа | низкий | высокий | низкий | минимальный |
| Подходит для публичного API | да | да | нет | нет |
| Тестируемость | хорошая | средняя | хорошая | средняя |
REST правильно
Если выбрали REST — следуйте конвенциям:
- Существительные в URL (
/users/42), не глаголы (/getUser). - HTTP-методы по смыслу: GET (чтение), POST (создание), PATCH (частичное), DELETE.
- Пагинация:
?limit=20&cursor=xyzили?page=2&size=20. - Фильтры:
?status=active&category=clothing. - Версионирование через URL:
/v1/..., или через заголовокAccept: application/vnd.api.v2+json. - Документация — OpenAPI 3.1 (Swagger), генерация клиентских SDK через openapi-codegen.
# openapi.yaml
paths:
/users/{id}:
get:
summary: Получить пользователя
parameters:
- name: id
in: path
required: true
schema: { type: integer }
responses:
'200':
content:
application/json:
schema: { $ref: '#/components/schemas/User' }
GraphQL правильно
- Используйте DataLoader для N+1.
- Лимиты: depth ≤ 10, complexity ≤ 1000.
- Persisted queries для production — клиенты шлют не запрос, а его hash, сервер уже знает реальный query. Это даёт CDN-кеширование и безопасность.
- Federation (Apollo Federation, GraphQL Mesh) — для микросервисов.
- Pothos или TypeGraphQL — для type-safe schema на TypeScript.
Стоимость поддержки
| Подход | Время на feature | Поддержка через год |
|---|---|---|
| REST с OpenAPI | средне | стабильно |
| GraphQL | дольше (схема + resolvers + типы) | стабильно при дисциплине |
| tRPC | быстрее всего | стабильно для TS-команды |
| Server Actions | мгновенно | стабильно для Next.js-only |
GraphQL медленнее на старте, но в проектах с быстро меняющимся UI окупается через полгода — фронтендеры не ждут бэкенд под каждый новый экран.
Когда GraphQL — точно нужен
- Mobile + Web + Watch + TV: один бэкенд для всех.
- Sumo-frontend: один экран дёргает данные из 5 микросервисов через federation.
- Большой фронт с многими тимами, бэкендеры не успевают добавлять эндпоинты.
- Публичный API типа Shopify, GitHub, Telegram — клиенты сами решают, что хотят.
Когда GraphQL — точно не нужен
- Команда из 2-3 разработчиков, один фронт.
- Простой CRUD без сложных связей.
- Высокие требования к HTTP-кешу и CDN.
- Команда без опыта GraphQL — кривая обучения убьёт месяца два.
Итого
В 2026 GraphQL — для специфичных случаев, не «по умолчанию для всего». Для большинства новых российских проектов: REST с OpenAPI, tRPC если стек TypeScript, server actions если Next.js. GraphQL — когда есть ясная техническая необходимость, не потому что «модно».
Частые вопросы
GraphQL медленнее REST?
Не сам по себе — оба упираются в одну БД. Но при наивной реализации GraphQL легко сделать N+1 запросов, и тогда страница тормозит. С DataLoader или batched queries — скорость сравнима. На уровне сети GraphQL обычно лучше: один POST вместо нескольких GET. На уровне HTTP-кеша REST выигрывает.
Можно ли совместить REST и GraphQL в одном проекте?
Да, обычное явление. REST для публичного API, GraphQL для внутреннего фронта. Или REST для простых эндпоинтов, GraphQL для сложных вложенных. Один сервер, две точки входа. Главное — не дублировать бизнес-логику, а вынести её в общий слой services.
tRPC можно использовать с не-TypeScript клиентами?
Технически можно, tRPC — это HTTP под капотом, но смысл теряется. На клиенте Python или Go вы получаете обычный JSON-ответ без типов, и проще сразу взять REST. tRPC силён именно сквозной типизацией TS↔TS.
GraphQL Federation — это сложно?
Да. Apollo Federation требует отдельного gateway-сервиса, координации schema между микросервисами, runtime-композиции запросов. Для команды из 5+ человек на 5+ микросервисах — окупается. Для маленького стартапа — катастрофа сложности на ровном месте.
REST устарел?
Нет, это базовый протокол современного веба. Большинство публичных API мира — REST: Stripe, GitHub, Twilio, ЮKassa, Yandex Maps. Если завтра выложите публичное API в формате GraphQL — половина клиентов сначала будет искать REST-обёртку. REST — это lingua franca, GraphQL — это специальный инструмент для специальных случаев.
Как версионировать API без боли?
Лучшая практика — backward-compatible изменения: добавляете поля nullable, не удаляете старые сразу, депрекейтите через заголовок Deprecation. В GraphQL — через @deprecated directive и удаление через 6-12 месяцев. Если совсем breaking change — /v2/ URL. Параллельно поддерживаете обе версии полгода и постепенно переводите клиентов.
Нужен ли GraphQL для мобильного приложения?
Если приложение стандартное (показ списка, детали, форма) — REST хватит. Если у вас сложная бизнес-модель с вложенными связями (соцсеть, маркетплейс), и вы хотите экономить трафик пользователя на медленной мобильной сети — GraphQL даст реальный выигрыш. Также часто берут GraphQL, когда мобильное приложение и веб делают разные команды и хотят независимости от бэка.