Gymterview
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

  1. Разные потребности клиентов — мобильному приложению нужен минимум данных (экономия трафика), веб-приложению — полный набор полей.
  2. Агрегация данных — BFF объединяет данные из нескольких микросервисов в один ответ.
  3. Разная частота изменений — мобильное приложение обновляется реже, его 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 — специализированный для каждого типа клиента. Частая ошибка — путать эти два паттерна.