惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

博客园_首页
I
InfoQ
The Register - Security
The Register - Security
L
LangChain Blog
H
Help Net Security
The GitHub Blog
The GitHub Blog
S
Schneier on Security
博客园 - 【当耐特】
W
WeLiveSecurity
Attack and Defense Labs
Attack and Defense Labs
IT之家
IT之家
CTFtime.org: upcoming CTF events
CTFtime.org: upcoming CTF events
Google DeepMind News
Google DeepMind News
The Cloudflare Blog
H
Heimdal Security Blog
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
Y
Y Combinator Blog
雷峰网
雷峰网
N
Netflix TechBlog - Medium
Security Archives - TechRepublic
Security Archives - TechRepublic
cs.AI updates on arXiv.org
cs.AI updates on arXiv.org
Cyber Security Advisories - MS-ISAC
Cyber Security Advisories - MS-ISAC
L
Lohrmann on Cybersecurity
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
T
The Exploit Database - CXSecurity.com
P
Privacy & Cybersecurity Law Blog
G
GRAHAM CLULEY
Exploit-DB.com RSS Feed
Exploit-DB.com RSS Feed
V
Visual Studio Blog
博客园 - 聂微东
PCI Perspectives
PCI Perspectives
Last Week in AI
Last Week in AI
A
Arctic Wolf
宝玉的分享
宝玉的分享
T
The Blog of Author Tim Ferriss
S
Secure Thoughts
T
Threat Research - Cisco Blogs
GbyAI
GbyAI
云风的 BLOG
云风的 BLOG
D
Darknet – Hacking Tools, Hacker News & Cyber Security
S
SegmentFault 最新的问题
SecWiki News
SecWiki News
月光博客
月光博客
大猫的无限游戏
大猫的无限游戏
Schneier on Security
Schneier on Security
P
Proofpoint News Feed
博客园 - Franky
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
AI
AI
Engineering at Meta
Engineering at Meta

Все публикации подряд на Хабре

Ловим музу за клавиатуру: как айтишнику стать автором Что умеет Midjourney в 2026? Мой немного грустный разбор этого шикарного инструмента Никто не любит писать тесты, но ИИ может исправить это IPv8 выглядит как мечта. Поэтому почти наверняка не взлетит Производители вернули в продажу материнки с DDR3. Что происходит? Управление агентом с телефона через Telegram теперь в KodaCode От координации к лидерству: как меняется роль руководителя разработки Я сделала родителям бизнес вместо пенсии: зарабатываем 70 тысяч, мама не даёт продать В три раза быстрее приемка товара и оптимизация трудозатрат на 73%: как «РСТ-Инвент» помог Gulliver Group ИИ-шечный мир победил? О влиянии искусственного интеллекта на игропром Кремль снижает давление на Телеграмм пока Европа строит интернет по паспорту Как CEO, CTO и CIO за 8 часов собрали ИИ-директора, который умеет держать позицию под давлением Как (не) потерять домен за выходные Вместо 8 разных VPS: как я организовал практику студентам на одном сервере Почему твой Open Source проект не замечают? R&D: искусство управления неопределенностью в разработке AI-дефляция: вакансий для разработчиков больше, а рост зарплат — худший за 15 лет Мы отдали управление роботами OpenClaw. Что из этого вышло Галактический ID: система идентификации для всех форм разумной жизни Шесть основ бизнес-анализа: начинаем с вопроса «Кто в игре?» Код-ревью, в котором дело не в коде Данные переехали. Команда — нет Системной подход к сдаче OSWE в 2025 Почему комната управления реактором покрашена в цвет морской пены 4 YAML-файла вместо PySpark: как аналитикам строить пайплайны без разработчиков LLM-агент для поиска свободных доменов: автоматизируем подбор Когда, зачем и как правильно начинать новую сессию в Claude Code? Как я заставил нейросеть писать макросы для FreeCAD Анатомия ИИ‑агента для подбора персонала. От тысячи резюме к топ‑10 за минуты Опыт разработчика как экономика внимания Автономность как точка невозврата: кто будет субъектом в цифровом будущем Обучение ИИ в «диких» условиях: как рутинные действия превращаются в датасеты Как измерить LLM для задач кибербеза: обзор открытых бенчмарков Где хранить код? Сравнение GitHub, GitLab и Bitbucket Математика объясняет, почему нормальное распределение встречается повсюду Почему ваш FinOps не работает: 12 тезисов от практиков Как подписать проектную документацию УКЭП с использованием бесплатных лицензий Pilot Адаптивное администрирование Sigla Vision Я грузил уран в бочки, а потом 20 лет строил ИТ в атомной отрасли Чем позвонить с Эвереста? История и обзор спутниковой связи. Часть 2 Как языковая модель помогает контролировать качество инструктажей по охране труда в металлургии Как не передать на desktop свой IP в РКН Анатомия SAP Privileges: как устроено управление правами в macOS MoneyDev: Сказка про три главных слова Обновлённый токенизатор видео K-VAE 2.0 от Сбера Как сделать диспетчеризацию дома на 1284 квартиры почти бесплатно Как мы разогнали железную дорогу Мы дали агентам рутину. Теперь надо решить — что делать с освободившимся временем Токсичный контент, промпт-хакинг и защита ИИ — всё о Guardrails для LLM Умный город начинается с точного взгляда: как «Фалькон Тех» меняет пространство к лучшему Навайбкодил приложение для анализа графов Почему Дюну так интересно читать? Упрощаем работу с рутиной или как стать Гендальфом Белым Деконструкция Go: CPU, RAM и что там происходит. Go Assembler база. Часть 1.1 Какие профессии исчезнут из-за ИИ, а какие появятся? И что с этим делать Как мы построили IT-отдел, где хочется расти: архитектурные встречи, прозрачные метрики и книжные подарки Rufler: Делаем из Claude Code автономный рой через один YAML-конфиг Sing-box и белый список приложений Как построить надёжный обмен сообщениями в микросервисах: лучшие практики для enterprise OpenAI строит MLM-пирамиду, а McKinsey и Accenture помогают ей в этом Дом, который не построил Фишер (Часть 2) «Сверхзвуковой математик» против «Вдумчивого логиста»: битва алгоритмов 3D-упаковки Мультимодальные модели – грубый и дорогой инструмент Разговоры ничего не стоят. Код тоже Проверки физических лиц: с кого начнет ФНС Топ-10 бесплатных нейросетей для создания видео в 2026 году Первые слои кода: как наши решения сегодня определяют архитектуру ИИ на десятилетия Разработка нового статического анализатора: PVS-Studio JavaScript Поиск уязвимостей ПО: базовый минимум или роскошный максимум Почему оценка персонала не работает как инструмент управления Как мы разработали ИИ-ассистента и сократили рутину продуктовой команды на 50% Как я ушел из найма, нажарил косточек и продал на маркетплейсах на 168 млн в год Когда 1С:ERP уже внедрена, а нормального производственного плана всё ещё нет Как я сделал Claude мультимодальным, подключив к нему Qwen Omni Как приглашение на вакансию мечты превращается в атаку Infrastructure as Code: философия и лучшие практики IaC Тестируем Yandex Code Assistant на задаче, в которой нужно хранить секреты nxs-universal-chart v3.0: новое поколение универсального Helm-чарта Callback Injection: Техника, которая отправила Microsoft Defender в глухой нокаут «Все идеи на стол»: митап как способ вывести проект из тупика Сегодня я узнал нечто новое о GPU благодаря багу в своей игре Как заставить LLM ̶ ̶г̶а̶л̶л̶ю̶ ̶ эволюционировать Карта событий как фундамент аналитики: практический кейс для E-commerce Что выбрать для AI: x86, ARM или RISC-V? Дайджест железа за март Роль соматических мутаций в развитии аутоиммунных заболеваний: путь к избирательной терапии Mythos от Anthropic — тревожный сигнал для всех, а не только для банков Guardrails для LLM на Java: как приручить промпт‑инъекции и токсичные ответы Green-VLA: как мы собрали VLA-модель для реального антропоморфного робота и не потеряли обобщение Финансовая гонка вооружений: почему умные люди добровольно в ней участвуют Эра ИИ-агентов наступила: выбираем лучшего цифрового сотрудника # Практический опыт внедрения WinCC Redundancy на производственном предприятии Сделал MVP за 3 дня, а потом неделю прикручивал оплату. Оно того стоило? Физика против Маска: почему Starship V3 может оказаться ещё одной катастрофой Нефть Венесуэлы: крупнейшие запасы в мире, но не крупнейшая нефтяная держава JPA 4. Переосмысление Hibernate Почему зеркальная фотокамера Nikon D5 десятилетней давности идеально подошла для миссии «Артемида-2» Проект «Уровень-Спутник» или как мы сделали платформу для гидрологов «Замедлиться, чтобы ускориться»: почему ИИ повышает цену ошибок в требованиях и архитектуре Как с нуля поднять трафик IT-компании на 1657% при бюджете 55 тыс. и выжить Pixel-perfect Downsampling — идеальная отрисовка 50 миллионов точек без потерь
Паттерн Backend for Frontend (BFF) в разработке современных приложений
cvartan (Син · 2026-05-22 · via Все публикации подряд на Хабре

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

В поисках решения я столкнулся с подходом 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-сервиса позволяет разорвать эту зависимость. Команда фронтенда получает свой собственный «бэкенд», который может развивать в нужном ей темпе, не отвлекая команду, ответственную за ядро системы. Конфликты между командами из-за разной скорости работы сходят на нет.

  • Лёгкое подключение новых клиентов. Появилось у нас мобильное приложение или, скажем, терминал для самообслуживания? Не проблема. Мы не трогаем основные сервисы, а просто пишем для нового клиента свой 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 — это не просто паттерн, это философия. Философия разделения ответственности, которая позволяет бизнес-логике оставаться чистой и стабильной, а интерфейсам — развиваться и экспериментировать. Это способ подружить два мира, живущих в разном ритме.

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