Привет, Хабр! Я — Константин Вартаньянц, системный аналитик-эксперт в «Синимекс». Мне приходится проектировать системы на микросервисах, и я нередко  сталкиваюсь с одной и той же историей: как построить бэкэнд для сложных приложений со множеством фронтендов.

В поисках решения я столкнулся с подходом Backend for Frontend, использовал его для проектирования и реализации нескольких систем и теперь хочу поделиться своим опытом.

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

Начну с главного. Какая главная задача у бэкенда, где крутится вся бизнес-логика? Правильно, обслуживать бизнес-процессы. Для него пользователь — это просто управляющий элемент: прилетели данные и команды, он их обработал, вернул результат и процесс пошел дальше. Ему глубоко всё равно, какой кнопкой, формой или голосом эти данные ввели. А вот у фронтенда работа другая — сделать так, чтобы пользователю было удобно, понятно и приятно. Это мир UX-гипотез, A/B-тестов и постоянной борьбы за лучший интерфейс. И для всех этих «рюшечек» и экспериментов ему нужны данные, которые в строгой бизнес-логике обычно не предусмотрены.

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

В итоге получается, что стабильная по своей природе бизнес-логика начинает дёргаться от каждой «косметической» правки в интерфейсе. Решили на фронте добавить пару колонок в таблице — и вот уже летит задача на доработку бэка. Это не только усложняет код, но и кратно повышает риск регресса (ситуации, когда после обновления ломается то, что раньше работало). 

Добавьте к этому, что у нас часто не один, а несколько фронтендов: веб-сайт для клиентов, админка для сотрудников, мобильное приложение. У каждого свои пользователи, свои сценарии и свои «хотелки». Чтобы угодить всем, бэкенд-разработчикам приходится плодить десятки почти одинаковых методов, которые раздувают кодовую базу и усложняют тестирование.

И далее, самая больная тема — безопасность. Если бэкенд отдаёт «сырые» данные, а фронтенд сам решает, что показать пользователю, а что нет, — это огромная дыра в безопасности. Любой студент, открывший инструменты разработчика в браузере, увидит всё, что от него пытались скрыть. 

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

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

Что такое BFF и как он работает

Место BFF в архитектуре системы
Место BFF в архитектуре системы

Этот посредник и есть Backend for Frontend (BFF). Суть паттерна проста: мы создаём отдельный, специализированный бэкенд для каждого типа клиентов (например, один для веб-приложения, другой — для мобильного). BFF не содержит собственной бизнес-логики. Его задача — быть переводчиком и адаптером между миром фронтенда и миром бэкенда. Он забирает на себя всю логику подготовки данных, освобождая от неё как основные сервисы, так и клиентские приложения. В идеальном мире у каждого фронта свой BFF, но в реальности похожие клиенты могут делить один общий BFF на всех.

Как это работает? Основные бизнес-сервисы очищаются от всего, что связано с «красотой»: в них остаются только чистые методы, реализующие бизнес-логику. Всю грязную работу берёт на себя BFF: он стучится в разные микросервисы, собирает от них данные, форматирует, фильтрует и отдаёт фронтенду в идеально готовом для употребления виде. В результате команда фронтенда может менять интерфейс как угодно — пока это не затрагивает суть бизнес-процесса, бэкенд-разработчики могут спать спокойно.

Вопрос безопасности, о котором я говорил, тоже элегантно решается. BFF, находясь в защищённом контуре, получает от внутренних сервисов все данные, включая конфиденциальные. Затем, зная права текущего пользователя, он, как строгий охранник, отсекает всё лишнее и отправляет на фронт только то, что разрешено видеть. Никакие секреты больше не утекают в браузер. Более того, BFF может управлять не только данными, но и логикой интерфейса, сообщая фронту, какие кнопки и поля показывать, а какие — прятать.

Плюсы и минусы подхода BFF

Перечислим плюсы, которые дает внедрение паттерна Backend for Frontend. 

  • Максимальное «облегчение» фронтенда. Вся сложная логика — агрегация данных из разных источников, фильтрация, подготовка — переезжает на BFF. Фронтенд превращается в тонкого клиента, чья задача — просто красиво отрисовать то, что ему прислали, и реагировать на действия пользователя. BFF может даже присылать готовые флаги-подсказки: «эту кнопку показывай, а эту — скрой».

  • Упрощение клиент-серверного взаимодействия. Вместо серии вызовов с клиента к разным сервисам выполняется один запрос к BFF, который сам обходит нужные системы. Поскольку взаимодействие между сервисами бэкенда быстрее и надежнее, чем обращения из внешней сети (особенно, когда взаимодействие фронта и бэка выполняется через интернет), общая производительность и стабильность возрастают.

  • Разные темпы разработки. У бизнес-логики и логики взаимодействия с пользователем совершенно разные жизненные циклы. Бизнес-процессы меняются редко и основательно. Интерфейс — это динамичная среда, где постоянно проверяются гипотезы и меняется дизайн. Выделение BFF-сервиса позволяет разорвать эту зависимость. Команда фронтенда получает свой собственный «бэкенд», который может развивать в нужном ей темпе, не отвлекая команду, ответственную за ядро системы. Конфликты между командами из-за разной скорости работы сходят на нет.

  • Лёгкое подключение новых клиентов. Появилось у нас мобильное приложение или, скажем, терминал для самообслуживания? Не проблема. Мы не трогаем основные сервисы, а просто пишем для нового клиента свой BFF. Это также упрощает поддержку старых версий приложений: можно менять API для новой версии, сохраняя совместимость для старой на уровне BFF.

Но, как известно, за всё хорошее надо платить. Внедрение дополнительного слоя в архитектуру — это не бесплатно.

  • Дополнительные сетевые задержки. Каждый запрос теперь делает лишний «прыжок» через BFF, что добавляет миллисекунды к общему времени ответа. Плюс, если раньше сложную фильтрацию могла делать сама база данных, то теперь BFF часто вынужден забирать избыточные данные по сети, чтобы отфильтровать их уже у себя в коде.

  • Усложнение инфраструктуры и эксплуатации. BFF — это не просто строчка на схеме, а полноценный сервис. Ему нужны свои серверы, процессы развёртывания, мониторинг и логи. Всё это — дополнительная головная боль для DevOps-инженеров и дополнительные расходы. 

  • Рост сложности разработки и дублирование кода. Логика теперь «размазана» по нескольким сервисам, что усложняет разработку и тестирование. А если у нас веб-сайт и мобильное приложение с похожими экранами, то, скорее всего, придётся написать два почти одинаковых BFF, а значит, и поддерживать дублирующийся код.

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

Когда без BFF не обойтись: критерии и стратегия внедрения

Разберёмся, какие флажки должны зажечься на дашборде проекта, чтобы всерьёз задуматься о внедрении BFF.

  1. У вас много разных клиентов. Если у вас один сайт и, может быть, в планах мобильное приложение, то, пожалуй, овчинка выделки не стоит. Но когда у вас уже есть веб для клиентов, админка для сотрудников и мобильное приложение для партнёров — это явный сигнал, что пора задуматься о BFF.

  2. Жёсткие требования ИБ. Если вам нужно жёстко контролировать, какие данные уходят на клиент, а впихивать эту логику в основные сервисы — значит превращать их в клубок спагетти, BFF — ваш выбор. Особенно это спасает при работе с унаследованными системами (legacy), которые трогать страшно и дорого. Проще поставить рядом с таким «чёрным ящиком» BFF-конвертер, который будет забирать из него всё, а наружу отдавать только разрешённое.

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

  4. Разные «скорости» разработки. Как я уже говорил, это организационный фактор. Если команда фронтенда постоянно торопится и экспериментирует, а команда бэкенда работает медленно и основательно, их совместная работа в одном репозитории превращается в вечный конфликт. BFF позволяет им разойтись по разным комнатам и не мешать друг другу.

Хорошо, допустим, мы взвесили все «за» и «против» и решили, что BFF нам необходим. 

Как его внедрять? 

Если проект только начинается, всё просто — слой BFF можно сразу заложить в архитектуру. 

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

Начать можно с так называемого смешанного режима. Простые запросы пусть продолжают ходить напрямую в основные сервисы (через API Gateway, то есть единую точку входа для всех запросов). А вот для новых, сложных задач мы сразу начинаем использовать BFF.

  • Путь первый: новые запросы — в новый сервис. Появляется в бэклоге задача, требующая агрегации данных из нескольких источников или хитрой логики разграничения прав? Отлично, мы не трогаем основной бэк, а сразу реализуем для неё отдельный метод в новом BFF-сервисе.

  • Путь второй: постепенный рефакторинг. В какой-то момент нам всё равно придётся модифицировать один из старых сервисов. И вот тогда, в рамках плановых работ, мы выносим из него методы, отвечающие исключительно за подготовку данных для клиентов, в соответствующий BFF-сервис.

Такой подход позволяет растянуть переходный период, внедрять изменения небольшими, контролируемыми порциями и не взрывать инфраструктуру и процессы разработки одним махом.

Проектирование BFF: от данных к экранам

Раз уж мы переносим логику с фронта на бэк, стоит упомянуть подход Screen as a Service. Суть его в том, чтобы проектировать API не вокруг абстрактных сущностей («пользователи», «заказы»), а вокруг конкретных экранов в интерфейсе. Мы думаем не «какие данные у нас есть», а «какие данные нужны пользователю на этом конкретном экране».

API для BFF идеально ложится на эту концепцию. Мы проектируем его «от экрана». Фронтенд говорит: «Дай мне всё для экрана „Карточка товара“», — и BFF возвращает один-единственный JSON, в котором уже всё собрано, отформатировано и готово к отрисовке. Внутри себя BFF сам сходит во все нужные сервисы, соберёт данные и применит все правила.

Чем это может помочь?

Во-первых, радикально облегчается спецификация API. Вместо описания десятков мелких методов для получения разрозненных данных, я описываю ресурсы-экраны. Техническое задание строится вокруг пользовательских сценариев: «Для экрана „Список заказов“ нужны такие-то поля, сгруппированные по статусу». И в результате появляется только один метод API, готовящий данные для этого экрана.

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

В-третьих, упрощается тестирование бэка для фронта. Можно проверить один-единственный эндпоинт, возвращающий экран целиком, вместо проверки на клиенте сложной цепочки вызовов.

Истории из жизни: как мы внедряли BFF

В дополнение к сказанному хотел привести примеры решения пары практических задач, которые решались с использованием данного паттерна.

История первая: собираем «зоопарк» в одном месте. У нас была система, где исторически каждый тип заявок (кредитные, сервисные и т.д.) жил в своём микросервисе. У каждого был свой формат данных и свой интерфейс. Пока пользователи работали с ними в разных разделах портала, всё было терпимо. Но со временем этот «зоопарк» разросся до неприличных размеров.

Появились новые требования: 

  1. Необходимо было создать единое рабочее место, где все заявки видны в одном списке, со сквозной фильтрацией и сортировкой, как будто данные и не были никогда разделены. И фильтровать они хотели по единому словарю, а не по разрозненным справочникам каждого отдельного сервиса. Вишенкой на торте стало требование, чтобы для разных типов заявок были доступны разные действия, причём их доступность определялась не только правами, но и содержимым самой заявки.

  2. Так как в списке будут все типы заявок, то необходимо при отображении или к обращении к заявке в списке учитывать привилегии пользователя для типа заявки.

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

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

  1. такое решение требовало серьёзной доработки имеющихся сервисов для организации репликации данных, а на это ресурсов не было, 

  2. не хотелось бы опять в рамках одного сервиса смешивать бизнес-логику и логику работы с фронтом (а в перспективе было, что для каждого нового типа заявки нужно было бы дорабатывать API).

Вариант с агрегацией данных на фронтенде отмёлся сразу из-за высокой нагрузки на клиентское устройство.

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

В случае получения общего списка заявок (с общим фильтром и сортировкой) фронтенд отправлял один-единственный запрос с фильтрами и параметрами страницы, а дальше начиналась обработка на стороне BFF.

Первым делом BFF-метод анализировал переданные с фронта фильтры. Если по типу заявок было видно, что в каком-то из сервисов-источников данных заведомо не будет, запрос туда просто не отправлялся. Для остальных же выполнялось преобразование: значения полей из общего фильтра переводились на язык, понятный каждому конкретному сервису, с использованием внутренних таблиц псевдонимов и правил трансформации значений.

Далее, поскольку наш BFF был «приклеен» к конкретному экземпляру фронтенд-приложения (через sticky session на API Gateway, механизм, который направляет все запросы одного пользователя на один и тот же сервер), он мог позволить себе хранить состояние между запросами. При переходе на следующую страницу списка сервис уже знал, что мы запрашивали раньше, и подгружал только недостающие данные, используя кэш.

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

И наконец, на последнем шаге, на основе привилегий текущего пользователя и данных каждой заявки, BFF вычислял доступные для неё действия: «редактировать», «просмотреть», «согласовать» и так далее. Эти флаги добавлялись прямо в объект с данными заявки. Фронтенду оставалось лишь отрисовать полученный список и показать нужные кнопки в каждой строке — никакой логики разграничения доступа на клиенте не осталось.

Что касается реализации новых требований безопасности для существующих сервисов, то в этом случае на стороне BFF использовались методы API, которые реализовывали существующую спецификацию (т. е. фронт достаточно было перенаправить по новым путям). А уже эти методы, получив данные от связанных бизнес-сервисов и информацию о привилегиях пользователя, дорабатывали ответ бизнес-сервиса, удаляя из него чувствительную информацию (или заменяя на “заглушки”).

Таким образом, фронтальное приложение стало получать готовый, обогащённый набор данных через один метод. Вся сложность маршрутизации, трансформации, агрегации, кэширования и применения прав доступа надёжно спряталась на стороне BFF, а на стороне бизнес-сервисов осталась только логика, нужная для выполнения бизнес-процесса. Это позволило нам решить задачу без рискованной переделки имеющихся систем и без риска превратить клиентское приложение в неповоротливого монстра.

История вторая: выносим всю логику авторизации из фронтенда. Раз уж у нас появился такой мощный инструмент, как BFF, мы решили пойти дальше и максимально «облегчить» фронтенд, вынеся из него всю логику, связанную с правами доступа.

Сложность была в том, что в компании жило несколько систем аутентификации и авторизации. Вдобавок к этому, у нас была собственная, довольно развесистая модель прав, которая использовала не только RBAC-подход (на основе ролей), но и ABAC (на основе атрибутов самих данных). Разбирать весь этот зоопарк на стороне фронтенда было бы трудоёмко и небезопасно.

Поэтому всю функцию определения видимости элементов интерфейса и, по сути, полной настройки GUI по ролям мы вынесли в слой BFF.

Для этого мы реализовали специальные методы в BFF-сервисе. При открытии формы она, функция, первым делом делала предварительный запрос к своему BFF, смиренно передавая ему тот токен авторизации, который ей достался от родительского приложения. BFF-сервис, как заправский полиглот, определял тип токена и его источник. Затем он обращался к нужным системам авторизации, получал базовые привилегии пользователя и обогащал их, применяя нашу собственную атрибутную модель доступа.

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

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

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

Вот, собственно, и всё. Как видите, BFF — это не просто паттерн, это философия. Философия разделения ответственности, которая позволяет бизнес-логике оставаться чистой и стабильной, а интерфейсам — развиваться и экспериментировать. Это способ подружить два мира, живущих в разном ритме.

Конечно, это не пуля из серебра, и за удобство приходится платить сложностью. Но в больших системах с кучей клиентов и жёсткими требованиями к безопасности игра, на мой взгляд, определённо стоит свеч. А как вы решаете подобные задачи? Встречали «монстров Франкенштейна» в своих проектах? Делитесь опытом в комментариях, будет интересно обсудить!

Комментарии (24)


  1. A-Dobrii
    21.05.2026 21:26

    Ну, поехали.

    Микросервис плодит надобность в ещё большем количестве микросервисов, теперь микросервис для облегчения интерфейсов.


  1. DmitryKazakov8
    21.05.2026 21:26

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

    Еще немаловажные фичи BFF - пререндеринг html, гибкое управление CSP и возможность более удобного тестирования. В компаниях, в которых работал, часто ресурса бэкенд-разработчиков было катастрофически мало, поэтому BFF занимались фронтендеры на node.js - и в целом хранить в одном репо и этот сервер, и код фронта, очень удобно. Можно переиспользовать схемы АПИ, графы условий показа функционала и использовать автоматические механизмы синхронизации (добавилась страница - создался бойлерплейт сервисов BFF для ее обслуживания) и проверки неиспользуемого функционала. Так контролируется рост техдолга в долгосрочной перспективе.

    В статье было интересно посмотреть, как к такой же схеме приходят со стороны бэкенда.


  1. GreedyGreen44
    21.05.2026 21:26

    Почему перечисленные в начале статьи проблемы, с которыми данный паттерн призван, вроде как, бороться, почти в том же виде повторяются в негативных последстивиях его внедрения?


    1. cvartan Автор
      21.05.2026 21:26

      На самом деле не совсем такие же (тут я скорее не совсем точно выразил мысль).

      Я тут вижу только в части сложности кода и разработки.

      В случае без BFF, например, в случае сложности разработки стоит говорить о том, что когда смешивается и бизнес-логика и логика взаимодействия с пользователем, в этом случае код получится запутанным, сложным в понимании что для чего (а как показала практика спецификация не всегда помогает потом),  ну и как уже писал, сложность разработки также в том, что  при внесении изменений в методы для фронта можем случайно сломать бизнес-логику (и такое, в моей практике, было достаточно часто). 

      Плюс проблема в разных циклах разработки для бэка и фронта. Т.е. проблемы больше организационно-технические.

      А сложность разработки и дублирование кода в минусах BFF возникает просто из-за очевидного факта того, что добавляется новый сервис. Но поддержка и понимание в дальнейщем получается в целом дешевле.

      И, понятное дело, что эта проблема возникает не на одном фронте и не на паре сервисов бэка - т.е. должна накопиться критическая масса, чтобы плюсы BFF превысили минусы без BFF и минусы BFF.


  1. MyraJKee
    21.05.2026 21:26

    Я против такого подхода... Он добавляет ещё один слой абстракции, да ещё как отдельный инстанс, который неизбежно несёт накладные расходы и так же может быть источником багов.

    При условии что у компании есть возможность контролировать исходный источник данных, почему бы не делать этот слой в сам бэкэнд сервис? На практике обычно для разных клиентов контракт один, различающийся незначительными деталями.

    Это напоминает работу ради работы...


    1. ivvi
      21.05.2026 21:26

      Тут вся статья про это, а вы такой вопрос задаёте...

      Во-первых, не всегда есть возможность (или желание) реализовывать в источнике данных дополнительные функции, помимо бизнес-логики. Например, в качестве источника выступает вендорское ПО, в которое нельзя просто так взять и прикрутить управление правами доступа, нужными фронту.

      Во-вторых, что если нужно в одном ответе фронту агрегировать (и фильтровать) ответы нескольких бэкенд-источников?

      В-третьих, BFF-сервис может держать в себе что-то, чему нет места в других источниках — ну, например, какие-то специализированные бизнес-справочники, чтобы подмешивать данные из них в ответ для фронта.

      И так далее.


      1. MyraJKee
        21.05.2026 21:26

        Вендорское ПО... Тогда вряд ли такой сервис можно будет назвать BFF.


      1. michael_v89
        21.05.2026 21:26

        в качестве источника выступает вендорское ПО

        В этом случае это должен быть внутренний сервис, к которому обращается бэкенд.

        если нужно в одном ответе фронту агрегировать ответы нескольких бэкенд-источников?

        Если сервис публично доступен для пользователя, то он должен сам обрабатывать права пользователя. Если он не обрабатывает права пользователя, он не должен быть доступен. Должен быть бэкенд, который его использует в своей логике, как любое другое third-party API с доступом по API KEY. Но это не BFF, а именно бэкенд с бизнес-логикой приложения.

        ну, например, какие-то специализированные бизнес-справочники

        Бизнес-справочники должны быть вместе с бизнес-логикой. Иначе на бэкенд приходит id, и фиг его знает, откуда он взялся, что он означает, и как логика от него зависит.


        1. cvartan Автор
          21.05.2026 21:26

          Если сервис публично доступен для пользователя, то он должен сам обрабатывать права пользователя. Если он не обрабатывает права пользователя, он не должен быть доступен. Должен быть бэкенд, который его использует в своей логике, как любое другое third-party API с доступом по API KEY. Но это не BFF, а именно бэкенд с бизнес-логикой приложения.



          Вот этот комментарий скорее всего к "Во-первых, не всегда есть возможность (или желание) реализовывать в источнике данных дополнительные функции, помимо бизнес-логики. Например, в качестве источника выступает вендорское ПО, в которое нельзя просто так взять и прикрутить управление правами доступа, нужными фронту."
          Потому что при наличии BFF готовить данные для фронта - его задача, в отсутствие BFF - ну либо задача самого фронта, либо выбирается один бизнес-сервис, который сам, при необходимости, опрашивает другие сервисы на предмет получения дополнительных данных, либо в него реплицируются данные других сервисов (это вполне себе вариант решения, если он дешевле создания BFF).
          Как я писал в статье - всегда надо смотреть, что дешевле. На простой системе, с парой интерфейсов, которые к тому же не часто меняются (например, системы для внутренних пользователей) - то слой BFF лишний.
          Если у системы есть внешние пользователи, если есть маркетинг, который постоянно "дорабатывает" GUI для них - то стоит задуматься. Тут просто то, что изменения для фронта будут внедряться быстрее уже может быть выигрышным (так как не надо будет при каждом изменении запроса фронта дергать бэк с основной бизнес-логикой).


          1. michael_v89
            21.05.2026 21:26

            Вот этот комментарий скорее всего к

            Этот комментарий к тому тексту, который я процитировал. Не нужно считать, что вы лучше меня знаете, что я хотел сказать.

            либо выбирается один бизнес-сервис

            Это и есть бэкенд с бизнес-логикой. В нем должна быть проверка прав доступа и слой представления.

            при наличии BFF готовить данные для фронта - его задача

            Готовить данные для фронта это задача любого бэкенда, который доступен с фронта. А правильнее говорить не “для фронта”, а “для пользователя”, и это вопрос не UI, а безопасности данных. Бэкенд не должен давать в ответе пользователю данные, к которым у него нет доступа, даже если пользователь отправил запрос через curl. И это правило работает даже если это запросы между сервисами во внутренней сети, просто обычно у других внутренних сервисов больше прав доступа, чем у обычных пользователей.

            всегда надо смотреть, что дешевле

            Это не вопрос того, что дешевле, это вопрос правильной архитектуры. Фронтенд не должен напрямую обращаться к внутренним микросервисам. Если микросервис доступен пользователю через интернет, в нем должна быть система авторизации. Если недоступен, значит обращения к нему это часть бизнес-логики, которая находится в другом микросервисе, где есть авторизация. Но это не BFF, а нормальный полноценный бэкенд. Воспринимайте недоступные пользователю микросервисы как базы данных с хранимыми процедурами, тогда будет понятно.

            например, системы для внутренних пользователей

            Нет никакой разницы, внешние они или внутренние. Проверка прав доступа при вызове бизнес-логики или при возвращении данных все равно должна быть.

            так как не надо будет при каждом изменении запроса фронта дергать бэк с основной бизнес-логикой

            Его и так не надо дергать. Если вам надо, значит вы что-то неправильно спроектировали. Без примеров непонятно, что вы имеете в виду.


    1. cvartan Автор
      21.05.2026 21:26

      Абстракция ради абстракции (как и подход ради подхода) всегда плохо. Они должны решать какую-то проблему, причем это решение должно, по итогу, быть дешевле чем потери от самой проблемы и минусы нового решения.

      Я, собственно, в статье и есть оговорка про то, что перед внедрением BFF надо подумать - а стоит ли это того.

      И Вы тут как раз повторяете то, что я вначале озвучил в проблемах - просто на начальном этапе это незначительная дополнительная логика, а при росте системы, при возрастании количества разных потребителей оно становится проблемой.

      Например, "При условии что у компании есть возможность контролировать исходный источник данных, почему бы не делать этот слой в сам бэкэнд сервис? " - можно, и это делают - в самом начале не трудно дополнительно  сделать метод получения данных для формы списка, почему бы вместе со статусом не передать цвет его отображения и ссылку на иконку - сейчас то, это не займет много места в БД да и мы еще помним зачем эти странные поля status_color и status_icon_url добавили в таблицу payments? 

      Но а если система будет расти,  что будет потом, когда появятся новые требования? Например, из практики - разные статусы для внешних клиентов и админов, разные комментарии к статусам для разных ролей пользователя, разные цвета для одного и того же статуса, разные иконки (это только по оформлению).
      Потом для разных ролей пользователей выясняется, что одной роли надо показать один набор данных, другой - другой набор (да, можно решить одним методом, либо добавляя кучу if'ов внутри метода, либо отсылая на фронт один набор данных - фронт разберется -, но тут приходят безопасники и говорят - а почему простой оператор видит остаток на счет - а это потому, что мы отправили на фронт его (в контракте же он есть) и, хотя форма его не показывает, любопытный оператор освоил F12 и смотрит ответы от бэка в оригинале). 

      И в результате мы имеем проблему, которую надо решать, так как она мешает развитию (долгое время на анализ существующего решения при внесении изменений, постоянные доработки методов для фронта ломающие бизнес-логику или из-за бизнес-логики не позволяющие быстро донести изменения для фронта до прода - так как надо все протестировать, чтобы убедиться, что ничего дополнительно не сломали). И вот когда мы решаем проблему, мы вспоминаем, что есть такой вариант решения как добавить слой BFF (а статья как раз о том, чтобы сказать, что вот есть такой вариант), считаем сколько это будет стоить (и не только в "моменте", но и в перспективе) и когда поймем что выигрыш есть - тогда и добавляем.


      1. MyraJKee
        21.05.2026 21:26

        Как-то это делали же раньше без дополнительных микросервисов?

        Если грамотно спроектировать архитектуру, то это можно сделать всё в одном сервисе. Чистая ахритектура, домены и вот это вот всё.


        1. cvartan Автор
          21.05.2026 21:26

          Ну многие проекты и до сих пор без этого живут.
          DDD не говорит о том, как сделать удобно пользователю работать с данными, он определяет базовую бизнес-логику. Он говорит о самих данных и какие основные действия с ними надо совершить чтобы получить требуемый результат, добавляет словарь чтобы разработчик с бизнесом говорил на одном языке - это как раз про "чистый" бэк, в котором реализована бизнес-логика.
          А BFF - это как раз про взаимодействие с пользователем.


  1. ivvi
    21.05.2026 21:26

    Константин, спасибо за статью. Просто, понятно и полезно.

    Но отмечу, что в плюсах и минусах подхода у вас продублировался пункт Упрощение клиент-серверного взаимодействия.


    1. cvartan Автор
      21.05.2026 21:26

      Да, спасибо за комментарий - пропустил при вычитке.
      Сейчас попробую поправить.


  1. alexanderfedyukov
    21.05.2026 21:26

    Константин, спасибо за интересный материал. Помогите пожалуйста разобраться: graphql не является ли одним из способов реализации задач BFF?


    1. cvartan Автор
      21.05.2026 21:26

      В части подготовки данных (точнее в части представления фронте только тех данных которые нужны) - да, как один из вариантов следует рассматривать. Но то же скажу, что это тоже не простое решение (может мне не везло, но сталкивался с тем, что многим аналитикам и разработчикам эта технология тяжело давалась - им проще было рядом еще один метод сделать).


  1. Dafostr
    21.05.2026 21:26

    Зачем плодить паттерны без необходимости? В DDD всё это уже заранее проработано – на уровне концепции ограниченных контекстов.


  1. FainFortRana
    21.05.2026 21:26

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


  1. michael_v89
    21.05.2026 21:26

    В коде смешивается доменная модель из DDD и логика подготовки данных для конкретной формы в интерфейсе.

    Значит код хреново написан, не должно так быть. Нет никакой проблемы из класса с бизнес-логикой возвращать модель, а в слое представления рендерить ее в нужное DTO.

    бэкенд-разработчикам приходится плодить десятки почти одинаковых методов

    А когда то же самое происходит в десятке разных BFF, то это вдруг становится нормально?
    Если нужно так делать в одном бэкенде, значит код хреново написан, не должно так быть.
    Если для разного набора полей не хочется добавлять полноценный GraphQL, то можно сделать GET-параметр со списком запрашиваемых полей, и обрабатывать его в слое представления.

    Решили на фронте добавить пару колонок в таблице — и вот уже летит задача на доработку бэка.

    Если это новые колонки, которых не было в ответе API, то без изменения бэка это не сделать. BFF тут ничего не меняет.

    Любой студент, открывший инструменты разработчика в браузере, увидит всё, что от него пытались скрыть.

    Открыли Америку.

    Отдавать всю модель прав на клиента — либо небезопасно, либо технически невозможно.

    Нет никакой проблемы отдать на клиента список прав текущего пользователя. Это его права, он их и так знает.

    сообщая фронту, какие кнопки и поля показывать, а какие — прятать

    Обычно это делается так, что бэкенд отдает клиенту роли текущего пользователя, а фронтенд знает какую кнопку для какой роли показывать. “Эта кнопка доступна только директору” это несекретная информация.

    Значит, бэкенд должен сам решать, что можно, а что нельзя.

    Нет. Бэкенд должен проверять соответствующие права при вызове действия через API. А как вы это действие вызываете с фронтенда, он знать не должен. Фронтенд сам должен знать какую кнопку для какой роли показывать. Да, иногда может быть рассинхронизания изменений, кнопка на фронтенде доступна, а на бэке действие возвращает ошибку, это просто следствие того, что у вас 2 независимые системы. Не нужно из-за этого интегрировать фронтенд в бэкенд.

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

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

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


    1. cvartan Автор
      21.05.2026 21:26

      Нет никакой проблемы из класса с бизнес-логикой возвращать модель, а в слое представления рендерить ее в нужное DTO.

      А разве это не есть разделение на слои? Да, тут внутри одного сервиса. в случае BFF разные сервисы. Но раз внутри одного сервиса, то могут быть еще другие факторы - например, тот же разный цикл реализациии презентационной логики и бизнес-логики.

      А когда то же самое происходит в десятке разных BFF, то это вдруг становится нормально?

      Ненормально - поэтому я и отнес это в минусы. 
      Но тут вопрос в том, что сколько у нас должно быть сервисов BFF и насколько они однотипные (идеал идеален в теории, но есть реальность и тут можно пойти на определенные уступки - то есть делить сервисы по группам ролей пользователей, например, один сервис для внешних пользователей, другой для внутренних бизнес-пользователей, третий для админов - некоторые проблемы, конечно, останутся, но тут хотя бы можно будет как-то разделить поток требований к фронту от разных групп пользователей - то есть и методы станут хоть и универсальные (например, один метод и для веб и для мобилки), но проще, да и реализацию изменений можно ускорить).

      Если для разного набора полей не хочется добавлять полноценный GraphQL, то можно сделать GET-параметр со списком запрашиваемых полей, и обрабатывать его в слое представления.

      И как озвучивал в проблемах - получим монструозный метод, оторванный от потребителя.

      Наличие слоя BFF можно обыграть с помошью спецификаций . Например, я логику методов BFF описываю в рамках постановки на GUI (конечно, разделяя документы, что тоже не получался архидокумент, но они по крайней мере лежат рядом) - и сразу видно для чего тот или иной метод нужен.

      Когда же я смотрю на спецификацию метода бэка (особенно, если сервис уже прожил больше года и активно развивался) я не всегда понимаю зачем это надо и как мои изменения могут это использовать или как на это повлиять (согласен, что это также вопрос документирования и комментирования, но я все-таки говорю про реальный мир, где работают реальные люди).

      Если это новые колонки, которых не было в ответе API, то без изменения бэка это не сделать. BFF тут ничего не меняет.

      А если были? И просто до какого-то момента не показывались? Например, в методе поиска не всегда для списка возвращают все данные - стараются ограничиться только тем, что надо показывать, а полные данные, например, получить когда уже пользовтаель откроет сущность на просмотр или редактирование.

      Нет никакой проблемы отдать на клиента список прав текущего пользователя. Это его права, он их и так знает.

      Если, конечно, нет ограничений по требованиям ИБ (это реальный случай в одном из крупных банков - безопасники требовали, чтобы в токене для внешних пользователей был только идентификационная информация, а уже привилегии добавляли в запрос на пути от фронта к бэку в слое API Gateway - естественно, фронт не знал какие там у пользователя привилегии).

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

      Ну так давайте сделаем это в виде одной системы? Как раз на слое BFF.

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

      А еще этот слой называется Backend for Frontend. Я дальше по тексту как раз про это и сказано.


      1. michael_v89
        21.05.2026 21:26

        А разве это не есть разделение на слои?

        Есть. А BFF тут при чем?
        Термин “представление (view)” появился лет 40 назад, а то и раньше. Он обозначает внутренную часть приложения, а не отдельное приложение.

        например, тот же разный цикл реализации презентационной логики и бизнес-логики.

        Что это означает? Для работы с кодом есть система контроля версий, код-ревью, система деплоймента. Им неважно, что именно делает код.

        поэтому я и отнес это в минусы

        Ну так тогда он не решает проблему, которую вы хотели решить с его помощью.

        то есть делить сервисы по группам ролей пользователей

        Не надо так делать. Когда делают например “админку”, это разделение по функциональности, а не по ролям. Внутри админки обычно точно так же есть проверка ролей.

        но тут хотя бы можно будет как-то разделить поток требований к фронту

        Требования к фронту реализуются на фронте. Если вы меняете для этого бэкенд, значит у вас код неправильно написан.
        Требование “Пользователю с ролью R не должно быть доступно поле F в этой таблице” это требование не к фронту, а к данным, которые возвращает бэкенд. Пользователь может и вручную отправить HTTP-запрос без всякого фронтенда.

        получим монструозный метод, оторванный от потребителя.

        Если у вас получается “монструозный метод”, значит вы пишете весь код в одном файле в одном классе в одном методе. Проблема тут не в требованиях и не в отсутствии BFF, а в вашем неумении писать структурированный код.

        Это решается в 30 строк один раз для всех методов API.

        Код
        ...
        $responseData = $this->runController(...);
        
        $fields = $this->request->getParams()->get('fields');
        if (is_array($fields) && is_array($responseData)) {
          $responseData = $this->processResponse($responseData, $fields)
        }
        
        return $responseData;
        
        
        function processResponse(array $srcResponseData, array $fields) {
          $finalResponseData = [];
          
          foreach ($fields as $field) {
            if (!isset($srcResponseData[$field])) continue;
            
            $value = $srcResponseData[$field];
            if (is_array($field)) {
              $subFields = $field;
              $finalResponseData[$field] = $this->processResponse($value, $subFields);
            } else {
              $finalResponseData[$field] = $value;
            }
          }
          
          return $finalResponseData;
        }
        

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

        Без примеров непонятно, что вы имеете в виду. Требования к GUI реализуются на фронтенде, он для этого и нужен.
        “Метод бэка” (который API-ендпойнт) нужен для предоставления данных фронтенду. Если он предоставляет не те данные, которые нужны, непонятно зачем он нужен. Выглядит так, что у вас внутренние сервисы торчат наружу без авторизации, и фронтенд может обращаться к ним напрямую.

        А если были? И просто до какого-то момента не показывались?

        Если они уже были в JSON, который бэкенд присылает фронтенду, вы их просто берете из ответа бэкенда и выводите в UI. В чем проблема-то?
        В любом другом случае нужны изменения на бэкенде.

        А если были?
        не всегда возвращают все данные

        У вас тут какое-то противоречие.

        безопасники требовали, чтобы в токене для внешних пользователей была только идентификационная информация

        Тут вопрос в том, как они предлагали скрывать элементы интерфейса в зависимости от привилегий.
        В любом случае это не требует какого-то специального BFF и нормально реализуется на обычном бэкенде.

        Ну так давайте сделаем это в виде одной системы? Как раз на слое BFF.

        Это будет не одна система, а три - фронтенд, бэкенд и промежуточный бэкенд. Только связанные в распределенный монолит.

        А еще этот слой называется Backend for Frontend.

        Нет, то что вы описываете это отдельное приложение, а не слой внутри кода бэкенда.


  1. cmyser
    21.05.2026 21:26

    Бред полнейший

    Делайте нормальный бэк, и будет вам счастье и не надо будет никаких bff придумывать ненужных


  1. UmbrellaLeaf5
    21.05.2026 21:26

    любопытный паттерн, спасибо за статью!

    по первому впечатлению похоже на некие умные специализированные под каждый фронт api-gateways

    только мучает вопрос, какие разработчики должны писать эти самые bff-сервисы? а то, получается, что по сути бэкенд, но нужны все данные о функционале конкретного фронта, а, значит, и часы на взаимодействие с разработчиками оттуда. как-то дороговато по человеко-часам может выйти...