Когда начинаешь проектировать API, рано или поздно встаёт вопрос: REST или GraphQL? Оба варианта рабочие, оба используются в продакшне крупными компаниями. Но у каждого есть своя область применения — и если промахнуться, потом будет больно.

Эта статья не про то, что «GraphQL — новый REST и все должны переходить». Это разбор конкретных ситуаций, где один подход выигрывает у другого.

Что такое REST и почему он до сих пор живёт

REST (Representational State Transfer) — это архитектурный стиль, а не протокол. Его придумал Рой Филдинг ещё в 2000 году, и с тех пор он стал стандартом де-факто для веб-API.

Основная идея: у каждого ресурса есть URL, а с ресурсом работают через HTTP-методы — GET, POST, PUT, DELETE. Хочешь получить список пользователей — GET /users. Хочешь создать нового — POST /users. Просто, предсказуемо, понятно любому разработчику.

Почему REST не умер, несмотря на появление GraphQL, gRPC и прочего:

  • Его понимают все. Любой джун знает, что такое эндпоинт.
  • Инструментарий огромный: Swagger, Postman, curl — всё работает из коробки.
  • Кеширование на уровне HTTP работает нативно.
  • Браузеры, CDN, прокси — всё заточено под HTTP-запросы.

Что такое GraphQL и зачем его придумали

GraphQL создали в Facebook в 2012 году, открыли в 2015-м. Причина простая: у Facebook сложный граф данных — пользователи, посты, комментарии, реакции, друзья друзей — и REST-подход с сотнями эндпоинтов превращался в кошмар.

Главная идея GraphQL: клиент сам описывает, какие данные ему нужны. Один эндпоинт (/graphql), один запрос — и получаешь ровно то, что просил, ни больше ни меньше.

Пример. Нужно показать карточку пользователя с именем, аватаром и тремя последними постами. В REST:

  1. GET /users/42 — получаем данные пользователя (но там ещё 20 полей, которые нам не нужны)
  2. GET /users/42/posts?limit=3 — получаем посты

В GraphQL один запрос:

query {
  user(id: 42) {
    name
    avatar
    posts(limit: 3) {
      title
      createdAt
    }
  }
}

Один запрос — ровно нужные поля. Никакого over-fetching (когда получаешь лишнего) и under-fetching (когда данных не хватает и надо делать второй запрос).

Где REST выигрывает

Простые CRUD-операции

Если ваш API — это набор ресурсов с базовыми операциями создания, чтения, обновления и удаления, REST — идеальный выбор. Интернет-магазин с товарами, корзиной и заказами? REST справится отлично.

Структура предсказуемая, любой сторонний разработчик разберётся без документации — по URL и методу сразу понятно, что происходит.

Публичные API

Если вы открываете API для внешних разработчиков — партнёров, интеграций, маркетплейсов — REST выигрывает по нескольким причинам:

  • Ниже порог входа для потребителей
  • Легче версионировать (/v1/, /v2/)
  • Стандартные HTTP-коды ответов понятны всем
  • Инструменты для тестирования работают без настройки

Вспомните крупные публичные API: Stripe, GitHub (у него есть и GraphQL, но REST-версия старше и шире поддерживается), Twilio — все REST.

Кеширование критично

HTTP-кеширование в REST работает нативно. GET-запросы кешируются браузерами, CDN и прокси без дополнительной настройки. Заголовки Cache-Control, ETag, Last-Modified — всё это работает из коробки.

В GraphQL большинство запросов идёт через POST, который не кешируется по умолчанию. Можно настроить кеширование на уровне приложения или использовать persisted queries, но это дополнительная работа.

Если ваш API отдаёт статичные или медленно меняющиеся данные — новости, каталог товаров, справочники — REST с кешированием снизит нагрузку на сервер в разы.

Файлы и бинарные данные

Загрузка файлов в REST — multipart/form-data, стандартный подход, который работает везде. В GraphQL с файлами история сложнее: официальной спецификации нет, используют разные обходные пути (multipart request spec, base64 в мутациях). Лишняя головная боль без очевидной выгоды.

Небольшие проекты

Если вы делаете лендинг с формой обратной связи или сайт-визитку — GraphQL здесь избыточен. Настройка GraphQL-сервера, схемы, резолверов занимает время, которое не окупится на простом проекте. REST или вообще простые HTTP-эндпоинты — правильный выбор.

Где GraphQL выигрывает

Сложный граф данных

Когда сущности в вашем приложении сильно связаны между собой и клиенту нужно часто получать данные из нескольких источников — GraphQL начинает блистать.

Социальная сеть, сложная CRM, маркетплейс с разветвлённой структурой данных — здесь GraphQL позволяет клиенту гибко запрашивать нужные связи без создания десятков специализированных эндпоинтов.

Несколько клиентов с разными потребностями

Это, пожалуй, главный аргумент в пользу GraphQL. Представьте: у вас есть веб-приложение, мобильное приложение и встраиваемый виджет. Каждому нужны разные наборы данных с одних и тех же сущностей.

В REST вы либо создаёте разные эндпоинты под каждого клиента, либо отдаёте всё — и мобилка получает 10 КБ там, где ей нужно 2 КБ. На медленном соединении это ощутимо.

В GraphQL каждый клиент запрашивает ровно то, что ему нужно. Мобилка берёт минимум полей, веб берёт больше — один API, одна схема.

Быстрая итерация на фронтенде

Команда фронтенда хочет добавить новое поле в карточку? В REST нужно либо договариваться с бэкендом о расширении эндпоинта, либо делать новый запрос. В GraphQL фронтенд просто добавляет поле в запрос — если оно есть в схеме, всё работает сразу.

Это ускоряет разработку, особенно когда фронт и бэк — разные команды.

Подписки и реальное время

GraphQL изначально поддерживает подписки (subscriptions) — механизм для получения данных в реальном времени через WebSocket. Это часть спецификации, и большинство GraphQL-серверов поддерживают это из коробки.

Чат, лента активности, уведомления — GraphQL subscriptions делают это удобно. В REST для реального времени используют WebSocket или SSE (Server-Sent Events), но это уже за рамками самого REST.

Интроспекция и самодокументирование

GraphQL-схема — это живая документация. Любой GraphQL-клиент может запросить схему через интроспекцию и узнать все доступные типы, поля и операции. GraphiQL и Apollo Studio превращают это в интерактивную песочницу.

Это особенно удобно для внутренних API, где документация часто устаревает — схема GraphQL всегда актуальна по определению.

Типичные ошибки при выборе

«GraphQL — это модно, давайте везде его»

Одна из самых частых ошибок — выбирать технологию по хайпу, а не по задаче. GraphQL добавляет сложность: нужно разбираться со схемой, резолверами, DataLoader для оптимизации запросов к БД, инструментами кеширования.

Если у вас три эндпоинта и простая структура данных — эта сложность не окупится.

«N+1 проблема решится сама»

Главная техническая ловушка GraphQL — проблема N+1. Если в резолвере для списка из 100 пользователей вы делаете отдельный запрос к БД для каждого пользователя — получаете 101 запрос вместо одного.

Решается через DataLoader (батчинг запросов), но это надо знать и помнить. Без этого GraphQL-сервер может быть медленнее REST-аналога.

Версионирование в REST как попало

Обратная ошибка: в REST часто версионируют криво. Добавляют /v2/ когда захочется, ломают обратную совместимость, оставляют /v1/ работать вечно. Результат — поддержка трёх версий одного API параллельно.

Правило простое: в REST не ломайте существующие контракты без крайней необходимости. Добавляйте поля, но не удаляйте и не меняйте существующие.

Можно ли использовать оба?

Да, и это нормальная практика. GitHub API существует в двух версиях: REST для простых операций (создание репозитория, работа с issues) и GraphQL для сложных запросов с вложенными данными.

Типичная схема: REST для публичного API и интеграций с партнёрами, GraphQL для внутреннего API между фронтендом и бэкендом. Каждый инструмент — на своём месте.

Практический чек-лист

Чтобы не мучиться с выбором каждый раз, вот простые вопросы:

Выбирайте REST если:

  • Простые CRUD-операции без сложных связей
  • Публичный API для сторонних разработчиков
  • Нужно нативное HTTP-кеширование
  • Команда маленькая, проект простой
  • Работаете с файлами
  • Небольшой бюджет и сроки (REST быстрее в разработке)

Выбирайте GraphQL если:

  • Несколько клиентов с разными потребностями (веб, мобайл, виджеты)
  • Сложный граф данных с множеством связей
  • Фронтенд и бэкенд работают независимо и нужна гибкость
  • Нужны подписки и реалтайм
  • Хотите интроспекцию и автодокументирование
  • Проблема избыточных данных в ответах критична (мобилка на медленном интернете)

Как это выглядит в реальных проектах

Возьмём конкретный пример. Интернет-магазин с каталогом товаров, корзиной и заказами. Три клиента: веб, мобильное приложение, CRM для менеджеров.

Веб показывает карточки с большим описанием, много изображений, отзывы. Мобилка показывает только название, цену и одно фото. CRM показывает складские остатки, себестоимость и историю продаж.

Это классический кейс для GraphQL: один API, три разных запроса под три разных представления.

А вот если у вас тот же магазин, но вы делаете интеграцию с маркетплейсом — отдаёте им данные о товарах и ценах — REST здесь логичнее. Партнёры привыкли к REST, у них готовые коннекторы, не надо объяснять GraphQL.

В REEXY при разработке интернет-магазинов (от 10 000 ₽) часто именно так и разделяем: GraphQL для внутреннего фронтенда, REST для внешних интеграций. Это не правило, а прагматика — каждый инструмент там, где он реально помогает.

Итог

REST и GraphQL — не конкуренты. Это инструменты с разными сильными сторонами.

REST — простой, понятный, с огромной экосистемой. Работает отлично там, где структура данных предсказуема и клиент один или мало.

GraphQL — гибкий, мощный, но требует больше усилий в настройке и понимании. Окупается там, где клиентов несколько, данные сложные, и фронтенд хочет независимости от бэкенда.

Если сомневаетесь — начните с REST. Его проще заменить на GraphQL позже, чем объяснять команде, почему вы усложнили простой проект. А когда GraphQL начнёт реально решать проблему, а не создавать новые — переходите.