Logo
Overview

API Gateway: зачем он нужен и как проектировать

May 8, 2026
7 min read

API Gateway — это не «ещё один nginx с модными словами». Это входная дверь в вашу распределённую систему, и именно от неё зависит, попадёт клиент к вам в дом или будет час стучать в закрытое окно.

Если у вас один сервис — забудьте про шлюз, вам он не нужен. Если у вас три сервиса и три фронтенда, и каждый фронт ходит сразу во все три — поздравляю, вы только что изобрели «архитектуру звезды» и скоро столкнётесь с тем, что любая мелкая правка авторизации требует деплоя пяти приложений (а ещё мобильного релиза, который ревьюится неделю).

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

Что такое API Gateway простыми словами

API Gateway — компонент, который принимает входящие запросы от клиентов, выполняет сквозные задачи (аутентификация, лимитирование, логирование, маршрутизация, трансформация) и проксирует их в нужные внутренние сервисы.

Если очень грубо — это администратор бизнес-центра. Курьер с пиццей не ломится сразу в офис на 14-м этаже: он сначала подходит к стойке, говорит, к кому пришёл, его проверяют, выписывают пропуск, объясняют, на каком лифте ехать. Шлюз делает ровно то же самое для HTTP-запросов: одна точка входа, единые правила, унифицированный контроль.

Важно: API Gateway — это паттерн, а не конкретный продукт. Реализаций много (Kong, Nginx с lua, Envoy, AWS API Gateway, Apigee, Traefik, Spring Cloud Gateway), и под капотом они могут быть устроены по-разному — от L7-прокси с конфигом до полноценного приложения с плагинами и хранилищем политик.

Чем шлюз не является

  • Не балансировщик. Балансировщик распределяет нагрузку между инстансами одного сервиса. Шлюз — между разными сервисами по правилам маршрутизации. Иногда роли совмещают, но смешивать в голове нельзя.
  • Не сервис-меш. Service mesh (Istio, Linkerd) занимается трафиком между внутренними сервисами. Gateway — только трафиком с улицы внутрь. Эти штуки часто живут вместе.
  • Не бизнес-логика. Если в шлюзе появилась логика расчёта скидки — это уже не шлюз, это микросервис с плохой репутацией.

Зачем нужен API Gateway: какие проблемы он решает

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

Шлюз нужен, когда хочется одно из следующего (а лучше всё сразу):

  • Единая точка аутентификации. Один раз проверить токен на входе — а не в каждом из пятнадцати сервисов. Подробнее про сами токены — в посте про OAuth и JWT для REST API.
  • Скрыть внутреннюю топологию. Клиенту не нужно знать, что заказ — это шесть микросервисов под капотом. Сегодня шесть, завтра восемь. Внешний контракт не должен от этого дёргаться.
  • Единые сквозные функции. Логирование, метрики, трейсинг, rate limiting, CORS, gzip — всё это должно жить в одном месте, а не размножаться по сервисам копипастой.
  • Разные клиенты — разные нужды. Мобилке нужен один JSON, веб-кабинету — другой, партнёрской интеграции — третий. Шлюз умеет агрегировать и трансформировать ответы (паттерн BFF — Backend for Frontend).
  • Контроль и квотирование. Партнёр платит за 1000 запросов в минуту? Это решается на шлюзе одной строчкой конфига, а не доработкой каждого сервиса.

Как спроектировать API Gateway: схема и потоки

Разберёмся, как в принципе устроен поток запроса. Тут важна не картинка ради картинки, а понимание, где принимается каждое решение и что может пойти не так на каждом шаге.

100%
graph LR
  subgraph CLIENTS["Клиенты"]
      WEB["Web SPA"]
      MOB["Mobile App"]
      PART["Партнёр / B2B"]
  end

  subgraph EDGE["Edge Layer"]
      CDN["CDN / WAF"]
      LB["Load Balancer"]
  end

  subgraph GW["API Gateway"]
      AUTH["Аутентификация / JWT"]
      RL["Rate Limiting"]
      ROUTE["Маршрутизация"]
      TRANS["Трансформация / агрегация"]
      LOG["Логирование / трейсинг"]
  end

  subgraph SERVICES["Внутренние сервисы"]
      S1["Order Service"]
      S2["Catalog Service"]
      S3["Payment Service"]
      S4["User Service"]
  end

  IDP["Identity Provider"]
  REG["Service Registry"]

  WEB --> CDN
  MOB --> CDN
  PART --> CDN
  CDN --> LB
  LB --> AUTH
  AUTH -.проверка токена.-> IDP
  AUTH --> RL
  RL --> ROUTE
  ROUTE -.lookup.-> REG
  ROUTE --> TRANS
  TRANS --> S1
  TRANS --> S2
  TRANS --> S3
  TRANS --> S4
  TRANS --> LOG

  style WEB fill:#4a90d9,stroke:#2c5f8a,color:#fff
  style MOB fill:#4a90d9,stroke:#2c5f8a,color:#fff
  style PART fill:#4a90d9,stroke:#2c5f8a,color:#fff
  style CDN fill:#f0a500,stroke:#c88400,color:#fff
  style LB fill:#f0a500,stroke:#c88400,color:#fff
  style AUTH fill:#50c878,stroke:#3a9a5c,color:#fff
  style RL fill:#50c878,stroke:#3a9a5c,color:#fff
  style ROUTE fill:#50c878,stroke:#3a9a5c,color:#fff
  style TRANS fill:#50c878,stroke:#3a9a5c,color:#fff
  style LOG fill:#50c878,stroke:#3a9a5c,color:#fff
  style S1 fill:#7b68ee,stroke:#5a4db2,color:#fff
  style S2 fill:#7b68ee,stroke:#5a4db2,color:#fff
  style S3 fill:#7b68ee,stroke:#5a4db2,color:#fff
  style S4 fill:#7b68ee,stroke:#5a4db2,color:#fff
  style IDP fill:#e0e0e0,stroke:#999,color:#000
  style REG fill:#e0e0e0,stroke:#999,color:#000

На диаграмме видно три зоны ответственности. Жёлтая — то, что вообще не наша головная боль на уровне приложения: CDN режет ботов и кэширует статику, балансировщик выбирает живой инстанс шлюза. Зелёная — собственно шлюз: пять стадий, через которые проходит каждый запрос. Фиолетовая — доменные сервисы, которые не должны знать ничего про токены, лимиты и CORS.

Стадии обработки запроса

  1. Аутентификация. Шлюз достаёт Authorization: Bearer ..., валидирует подпись JWT (по ключу из IdP) или дёргает introspection-endpoint. Невалидный токен — 401, и дальше в систему запрос не идёт. Сервисы получают уже распарсенный контекст пользователя в заголовке X-User-Id.
  2. Rate limiting. Проверяется по ключу (user_id, api_key, IP). Лимит превышен — 429, Retry-After в заголовке. Без шлюза вы будете писать этот код в каждом сервисе и обязательно где-нибудь забудете.
  3. Маршрутизация. По пути и заголовкам шлюз решает, кому отдать запрос. Адрес сервиса берётся из service registry или статического конфига. Версии API (/v1/, /v2/) — тоже сюда.
  4. Трансформация / агрегация. Иногда мобильному клиенту нужен один ответ, склеенный из трёх сервисов. Это паттерн BFF. Только не превращайте шлюз в god-object — об этом ниже.
  5. Логирование, трейсинг, метрики. Один X-Request-Id, который шлюз пробрасывает дальше, спасёт вас на проде в три часа ночи.

API Gateway vs прямые вызовы клиента: таблица сравнения

Чтобы стало совсем ясно — собрал в одну таблицу разницу подходов. Колонка «Без шлюза» — это про систему, где клиент ходит во все сервисы напрямую. Знакомая многим картина.

АспектБез шлюза (прямые вызовы)С API Gateway
АутентификацияДублируется в каждом сервисеОдна точка, один кодовый путь
Изменение топологииЛомает контракт клиентаПрозрачно для клиента
Rate limitingРазмазан или отсутствуетЦентрализованный, по политикам
Логи и трейсингНесвязные потокиЕдиный request_id сквозь систему
Версионирование APIКаждый сервис сам по себеУправляется маршрутами шлюза
Поддержка разных клиентовОдин контракт на всехBFF под мобилку / веб / партнёров
Точка отказаРаспределённаяШлюз — критичный SPOF
LatencyМинимальный+1 hop (обычно 1–5 мс)

Последние две строки — это не «минус шлюза», это плата, про которую нужно помнить. Если шлюз лёг — лежит вся внешняя поверхность. Поэтому он всегда в HA-конфигурации, минимум два инстанса за балансировщиком, желательно в разных AZ.

Антипаттерны: как не надо делать API Gateway

Есть пара вещей, на которых обжигались примерно все, кто строил шлюз с нуля. Расскажу, чтобы вы обожглись пореже.

God Gateway

Это когда в шлюз начинают засовывать всё подряд: бизнес-валидации, расчёт цены, маппинг состояний заказа. Через полгода у вас полноценный микросервис, который называется «gateway» и через который проходит 100% трафика. Деплой — раз в неделю с молитвой. Любая ошибка ронит весь продукт.

Правило простое: на шлюзе живёт только сквозная инфраструктурная логика. Если для добавления фичи нужно править шлюз — это не фича для шлюза, это фича для домена.

Один шлюз на всех клиентов

Заманчиво сделать один универсальный API и проксировать его всем. На практике у мобильного приложения, веб-кабинета и B2B-партнёра разные требования: к payload, к версионированию, к лимитам, к схеме авторизации.

Лучшее решение — несколько шлюзов под разные аудитории (внешний публичный, внутренний для админки, отдельный для партнёров). Каждый со своей политикой.

Синхронная агрегация поверх десяти сервисов

Когда шлюз для одного запроса вызывает десять backend-ов и склеивает ответы. На бумаге красиво, на проде это значит, что задержка ответа = max задержка по всем сервисам, а доступность = произведение доступностей. Если каждый сервис даёт 99.9%, десять синхронных вызовов — это 99%. Минус 8 часов в год.

Если правда нужно агрегировать много данных — отдавайте это либо асинхронно (см. событийную архитектуру и предсобранные read-модели), либо выносите в отдельный BFF-сервис, не валите на шлюз.

Шлюз без таймаутов и circuit breaker

Один медленный сервис — и шлюз превращается в очередь зависших соединений. Через минуту встают все клиенты, потому что треды кончились. Таймауты — обязательны, circuit breaker — желателен, retry с экспоненциальной задержкой — только если запрос идемпотентный.

Итого: когда внедрять и когда подождать

Шлюз — это инвестиция. Он окупается, когда у вас минимум 3–5 сервисов и больше одного типа клиента. На старте, когда у вас один монолит и один фронт, ставить шлюз — это карго-культ: работа есть, профита нет, дополнительный hop по latency и +1 компонент в SRE-карте.

Но когда количество сервисов начинает расти — а оно начинает расти быстрее, чем хотелось бы — шлюз превращается из «модной штуки из доклада» в банальную необходимость. Вопрос только в том, спроектируете вы его осознанно или вырастите случайно из nginx-конфига, который никто не помнит, кто и зачем писал.

PS. Самое удивительное: половина проектов внедряет API Gateway не потому, что он действительно нужен, а потому что «у соседей есть». Если у вас три эндпоинта и один React-фронт — вам не нужен Kong. Вам нужно дописать тесты. Работает — не трогай.