Москва: проверенные б/у ноутбуки с гарантией и проверкой перед оплатой
+7 906 722-94-45

Главная → Статьи → Backend-for-Frontend: отдельный API для каждого клиента

Backend-for-Frontend: когда общему API нужен отдельный слой

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

Прямой ответ

Backend-for-Frontend (BFF) — отдельный серверный слой, который обслуживает один тип клиента. Веб-приложение, мобильное приложение и партнёрский API получают каждый свой слой, настроенный под свои потребности, вместо одного универсального API.

Проблема, которую решает BFF: единый API вынужден удовлетворять всех сразу. Мобильному клиенту нужен один компактный ответ за один запрос, веб-версии — полный набор полей для таблицы, партнёру — стабильный контракт без внутренних деталей. В результате API обрастает параметрами, версионирование усложняется, а изменение под одного клиента ломает другого.

веб-клиент   -> web-bff   ┐
мобильный    -> mobile-bff ├-> заказы, каталог, оплата (доменные сервисы)
партнёр      -> partner-bff┘

BFF отвечает за три задачи:

Задача Что делает
Агрегация Собирает данные нескольких сервисов в один ответ под конкретный экран
Адаптация формата Отдаёт поля в виде, удобном клиенту, без лишних данных
Сокращение запросов Заменяет пять вызовов с клиента одним вызовом к BFF

Пример агрегации для мобильного экрана товара:

@router.get("/m/product/{product_id}")
async def product_card(product_id: str):
    product, price, stock = await asyncio.gather(
        catalog.get(product_id),
        pricing.get(product_id),
        warehouse.get_stock(product_id),
    )
    return {
        "title": product.title,
        "image": product.images[0] if product.images else None,
        "price": price.final_amount,
        "available": stock.quantity > 0,
    }

Клиент делает один запрос вместо трёх и получает только те четыре поля, которые показывает экран.

Ключевое свойство BFF — владение. Слой принадлежит команде, которая делает клиент, поэтому изменение интерфейса не требует согласования с владельцами доменных сервисов.

Практика: когда применять и как не переусложнить

1. Применяйте при расхождении потребностей клиентов. Если веб и мобильная версия нужны разные наборы данных, BFF оправдан. Если потребности совпадают, отдельный слой только добавляет задержку.

2. Не превращайте BFF в бизнес-логику. Слой агрегирует и адаптирует. Правила предметной области остаются в доменных сервисах; иначе логика дублируется в нескольких BFF и расходится.

3. Различайте BFF и API-шлюз. Шлюз — единая точка входа с аутентификацией, лимитами и маршрутизацией, общая для всех клиентов. BFF — слой под конкретного клиента. Они часто работают вместе: шлюз принимает трафик, BFF формирует ответ. О шлюзе — в статье про API Gateway.

4. Следите за дублированием. Три BFF, каждый со своей логикой агрегации, начинают расходиться. Общие части выносят в библиотеку или в отдельный сервис агрегации; о приёмах — в статье про композицию API.

5. Обрабатывайте частичные сбои. Один из трёх сервисов может быть недоступен. Экран товара без остатка полезнее, чем ошибка целиком; о паттернах устойчивости — в статье про retry и circuit breaker.

6. Версионируйте контракт BFF независимо. Слой принадлежит клиенту и меняется вместе с ним; о совместимости — в статье про версии API.

7. Не создавайте BFF на каждый экран. Один BFF на тип клиента — разумная гранулярность; десять слоёв на одно приложение не поддерживаются.

Рекомендации:

  1. Начинайте с одного клиента. BFF для мобильного приложения появляется, когда требования мобильного клиента перестали помещаться в общий API.
  2. Держите слой тонким. Объём кода BFF — индикатор: если там появились расчёты и правила, логика ушла не туда.
  3. Логируйте время каждого вызова к доменным сервисам. Агрегация скрывает медленный сервис за общим временем ответа.
  4. Кэшируйте осторожно. Кэш в BFF улучшает отклик, но добавляет собственный срок устаревания данных.
  5. Тестируйте на частичных отказах. Ответ с отсутствующим блоком должен быть валидным, а не падать на отсутствующем поле.

Практический сценарий: мобильное приложение делало девять запросов на один экран

Контекст: экран корзины в мобильном приложении выполнял девять последовательных запросов к разным сервисам. Время отрисовки на мобильной сети достигало четырёх секунд.

  1. Диагностика. Из девяти запросов семь возвращали данные, которые не отображались на экране: полные описания товаров, историю цен, технические поля.
  2. Причина. Приложение работало с общим API, спроектированным под веб-версию, где данные показывались на разных вкладках.
  3. Действия. (а) Добавили mobile-bff с одним методом для экрана корзины; (б) метод параллельно запрашивал три сервиса и возвращал семь полей вместо девяноста; (в) частичный сбой сервиса рекомендаций обрабатывался как пустой блок, а не как ошибка; (г) добавили кэш цен на десять секунд, поскольку точность до секунды на экране корзины не требовалась; (д) сохранили общий API для веб-версии без изменений.
  4. Результат. Число запросов с клиента сократилось с девяти до одного, время отрисовки — с четырёх секунд до 700 миллисекунд. Изменение состава экрана перестало требовать правок в доменных сервисах.

Вывод: BFF оправдан, когда потребности клиента расходятся с формой доменного API. Выигрыш даёт не новый слой сам по себе, а сокращение объёма передаваемых данных и числа сетевых обменов.

FAQ

Нужен ли BFF, если есть API-шлюз? Это разные задачи. Шлюз решает сквозные вопросы — аутентификацию, лимиты, маршрутизацию. BFF формирует ответ под конкретного клиента. Шлюз не заменяет адаптацию формата.

Кто владеет BFF? Команда, отвечающая за клиент. Это основное отличие от общего API, которым владеют владельцы доменных сервисов.

Не дублируется ли логика в нескольких BFF? Риск есть. Бизнес-правила должны оставаться в доменных сервисах; в BFF остаётся только агрегация и формат представления.

Можно ли использовать BFF для партнёрского API? Да, это один из типичных случаев: партнёру нужен стабильный контракт, который не должен меняться вместе с внутренними сервисами.

Источники: Sam Newman (BFF), microservices.io (API Gateway), Azure Architecture Center — ссылки в шапке.