Классическое взаимодействие через RESTful-API прекрасно, но не лишено недостатков. Часто из огромного джейсона приходится выковыривать крупицы данных. Или напротив, из собирать воедину ответ от трех-четырех ручек. Уверен, вы с таким сталкивались. Побороться с этим призвано такое архитектурное решение (или даже паттерн) как BFF. Сегодня мы разберемся, зачем нужен еще один слой между фронтом и бэком.
- Гастрономическая аналогия
- По-простому. Что такое BFF
- Проблемы, которые решает BFF
- Проблема №1: Оверфетчинг (передача лишних данных)
- Проблема №2: Андерфетчинг (нехватка данных)
- Проблема №3: Разные требования у разных клиентов
- Проблема №4: Сложность клиентского кода
- А правда ли всем нужен BFF?
- Недостатки BFF
- Альтернативы BFF
- Итого
Гастрономическая аналогия
В какой-то из статей я что-то объяснял через ларек с шаурмой. Сегодня мы вернемся к этому утопическому примеру. Итак, вы открыли лучшую шаурму на районе. В начале работы вы принимаете деньги сами, крутите шаурму сами, упаковываете в целофановые пакеты и выдаете клиентам через маленькое окошечко.
Бизнес идет в гору и вы открываете доставку. Рецепт шаурмы под нее вы не меняете, но вот упаковка — уже другая — например, алюминиевые боксы с картонной крышкой. В целофановом пакете она до покупателя не доедет. И сложность вашей работы кратко возрастает. Но сил пока хватает и вы делаете столики для того, чтобы клиенты могли употребить продукт на месте и с комфортом. Здесь вы выдаете блюда уже на тарелках и, может быть даже с приборами.
Переводя на язык программирования, вы только что совершили классическую ошибка в архитектуре апи. Наплодили разных методов, которые выполняют одно и то же, но выдают результат под разным соусом. Если перепоручить эту задачу кому-то другому, то можно сделать и бэкенд (приготовление шаурмы) и фронтенд (выдачу заказов) архитектурно чище и стабильнее.
В утопическом мире с ларьком шаурмы можно, например, нанять администратора, который будет упаковывать готовый продукт. А на проекте придется завести BFF.
По-простому. Что такое BFF
BFF — это отдельный сервис (или слой), который сидит между вашим фронтендом и основным бэкендом. Он работает так:
- Принимает запрос от фронта
- Идет в бэкенд-сервисы (в один или несколько одновременно), забирает данные
- Агрегирует и трансформирует данные под нужды конкретного фронта
- Отдает готовый ответ фронту в нужном формате.
BFF не содержит бизнес-логики. Он не считает скидки, не проверяет баланс, не сохраняет данные. Всю серьезную работу делает основной бэкенд. BFF — это что-то вроде переводчика или сборщика.
Проблемы, которые решает BFF
Проблема №1: Оверфетчинг (передача лишних данных)
У вас есть бэкенд, который отдает профиль пользователя. Отдает щедро:
{
"id": 123,
"name": "Вася",
"email": "vasya@mail.ru",
"createdAt": "2023-01-01",
"updatedAt": "2023-12-31",
"address": "...",
"phone": "..."
}
А на фронте для карточки пользователя нужно только name и email. Остальные данные в контексте этой задачи — мусор, который только увеличивает количество трафика, которое гуляет по сети.
Применяя BFF, мы получим такую схему: бэкенд отдает всё на BFF, а BFF отдает фронту только нужное.
{
"name": "Вася",
"email": "vasya@mail.ru"
}
Проблема №2: Андерфетчинг (нехватка данных)
У вас страница профиля, на которой нужно показать:
- Данные пользователя (из сервиса
user-service) - Аватар (из сервиса
file-service) - Количество подписчиков (из сервиса
social-service)
Без BFF фронт должен сделать 3 последовательных запроса:
GET /users/123→ получаем пользователя.GET /file/123/avatar→ получаем аватар.GET /social/followers/123→ получаем подписчиков.
Каждый запрос — это задержка (даже если 100 мс, 3 запроса = 300 мс). И это, допустим, на быстрой сети. А если запрос делается через дохленький 3G?
С BFF фронт сделает всего 1 запрос на BFF, например: GET /api/profile/123. BFF параллельно (или последовательно, если нужно) сходит в 3 сервиса, соберет данные, и отдаст все сразу.
{
"user": { "name": "Вася", "email": "vasya@mail.ru" },
"avatar": "https://cdn.site/avatar123.jpg",
"followersCount": 42
}
Один запрос вместо трех. Страница грузится быстрее.
Проблема №3: Разные требования у разных клиентов
- Веб-версия: нужны картинки, длинные тексты, много декоративных данных, медленный интернет не проблема.
- Мобильное приложение: нужны только ключевые данные, картинки маленькие, важна скорость и экономия трафика.
- Админка: нужны все данные, включая служебные (статусы, метаданные).
- Публичное API (для сторонних разработчиков): нужна стабильная структура, которая не меняется годами.
Бэкенд не может держать в голове требования всех клиентов. Он просто отдает «сырые» данные. А BFF можно сделать для каждого клиента свой:
bff-web.yourapp.com— для веба.bff-mobile.yourapp.com— для мобилки.bff-admin.yourapp.com— для админки.
Каждый BFF адаптирует данные под свой тип клиента.
Проблема №4: Сложность клиентского кода
Без BFF фронтенд превращается в спагетти-код из запросов:
// Без BFF — боль и страдания
const user = await fetch('/users/123');
const avatar = await fetch('/media/123/avatar');
const followers = await fetch('/social/followers/123');
const posts = await fetch('/posts/123');
// ... и так далее
С BFF код фронта куда как более чистый:
// С BFF — красота
const profile = await fetch('/api/profile/123');
Один запрос вместо четырёх. Вся логика агрегации ушла на сервер.
А правда ли всем нужен BFF?
BFF нужен, если:
- У вас на бэке микросервисная архитектура (много отдельных бэкендов)
- У вас несколько типов клиентов (веб, мобилка, админка, API для партнеров)
- Фронт делает много последовательных запросов для отображения оодной страницы
- Бэкенд отдает слишком много лишних данных
- Вы хотите, изолировать внутреннюю структуру бэкенда от внимания клиентов (так безопаснее).
BFF — скорее всего оверхед, если:
- У вас на бэке монолит
- У вас один тип клиента (например, только веб)
- Приложение простое и данных мало
Недостатки BFF
- BFF — это дополнительный сервис — егонужно разворачивать, поддерживать, мониторить. Это расходы
- Увеличение задержки — запрос сначала идет на BFF, потом на бэкенд, потом обратно. Поэтому BFF должен быть быстрым, иначе профита не будет
- Дублирование логики — если у вас несколько BFF (для веба, мобилки и админки), код частично дублируется. Решение — писать общие библиотеки, но это дополнительные издержки
- Сложность с кэшированием — агрегированные данные сложнее кэшировать, потому что они зависят от многих источников.
- Единая точка отказа — если BFF упал, все клиенты падают. Здесь нужно позаботиться о высокой доступности
Альтернативы BFF
- GraphQL
Вместо того чтобы писать BFF вручную, вы используете GraphQL Gateway (Apollo Federation). Клиент сам решает, какие данные ему нужны (через запросы), а шлюз собирает их с разных сервисов.
Плюсы: Гибкость (клиент сам выбирает поля), меньше кода для BFF.
Минусы: Сложность настройки, клиенты становятся «умными».
- Сервисный слой на фронте (Service Layer)
Вы не пишете отдельный сервер, а делаете на фронте слой, который выполняет задачи BFF — ходит в разные API и агрегирует данные.
Плюсы: Нет дополнительного сервиса.
Минусы: Все запросы идут с клиента, что медленнее и небезопасно (ключи доступа видны)
- API Gateway (более низкий уровень)
Это не BFF, а общий шлюз для всех запросов (маршрутизация, авторизация, лимиты). Он не агрегирует данные, просто перенаправляет запросы.
Плюсы: Все запросы проходят через единую точку, где можно централизованно управлять аутентификацией, лимитами, логированием и маршрутизацией, не трогая каждый микросервис по отдельности
Минусы: Если шлюз упал — упало всё приложение, плюс каждый запрос получает дополнительную задержку (5-20 мс)
Итого
BFF — это не панацея. Это инструмент для сложных проектов. Маленьким приложениям он не нужен, но когда проект разрастается, BFF становится спасением, которое избавляет фронтенд-команду от боли работы с множеством запросов и кучами лишних данных в рамках клиентского кода.
Желаю успехов!







