middle
Что такое паттерн BFF (Backend for Frontend)?
BFF (Backend for Frontend) — это паттерн, при котором для каждого типа клиента (мобильное приложение, веб-приложение, партнёрское API) создаётся отдельный backend-сервис, оптимизированный под потребности этого клиента.
Пример
┌──────────┐ ┌──────────┐ ┌──────────────┐
│ Мобильное│ │ Веб- │ │ Партнёрское │
│ прилож. │ │ прилож. │ │ API │
└────┬─────┘ └────┬─────┘ └─────┬────────┘
│ │ │
┌────▼─────┐ ┌────▼─────┐ ┌────▼────────┐
│ Mobile │ │ Web │ │ Partner │
│ BFF │ │ BFF │ │ BFF │
└────┬─────┘ └────┬─────┘ └─────┬───────┘
└──────────────┼───────────────┘
│
┌───────────┼───────────┐
▼ ▼ ▼
Payment Customer Notification
Service Service Service
Зачем нужен BFF
- Разные потребности клиентов — мобильному приложению нужен минимум данных (экономия трафика), веб-приложению — полный набор полей.
- Агрегация данных — BFF объединяет данные из нескольких микросервисов в один ответ.
- Разная частота изменений — мобильное приложение обновляется реже, его BFF может поддерживать старые форматы дольше.
Пример: Mobile BFF vs Web BFF
// Mobile BFF — минимум данных, оптимизация для мобильных
@RestController
@RequestMapping("/mobile/api")
public class MobileAccountController {
@GetMapping("/dashboard")
public MobileDashboardResponse getDashboard(@AuthenticationPrincipal User user) {
Account account = accountService.getMainAccount(user.getId());
List<Transaction> recent = transactionService.getRecent(user.getId(), 5);
return MobileDashboardResponse.builder()
.balance(account.getBalance())
.currency(account.getCurrency())
.recentTransactions(recent.stream()
.map(t -> new MobileTransactionDto(t.getAmount(), t.getDescription()))
.toList())
.build(); // Компактный ответ
}
}
// Web BFF — больше данных, сложные представления
@RestController
@RequestMapping("/web/api")
public class WebAccountController {
@GetMapping("/dashboard")
public WebDashboardResponse getDashboard(@AuthenticationPrincipal User user) {
List<Account> accounts = accountService.getAllAccounts(user.getId());
List<Transaction> transactions = transactionService.getRecent(user.getId(), 50);
AnalyticsData analytics = analyticsService.getMonthlyAnalytics(user.getId());
List<Notification> notifications = notificationService.getUnread(user.getId());
return WebDashboardResponse.builder()
.accounts(accounts)
.transactions(transactions)
.analytics(analytics)
.notifications(notifications)
.build(); // Полный набор данных
}
}
Когда использовать BFF
- Есть несколько типов клиентов с разными потребностями.
- Клиентам нужны агрегированные данные из нескольких сервисов.
- Разные команды отвечают за разные клиентские приложения.
Когда НЕ нужен BFF
- Один тип клиента — достаточно API Gateway.
- Все клиенты потребляют одинаковые данные.
На собеседовании: объясните отличие BFF от API Gateway. Gateway — общий для всех клиентов, BFF — специализированный для каждого типа клиента. Частая ошибка — путать эти два паттерна.