Мобільний застосунок робить 5–10 послідовних HTTP-запитів для завантаження однієї сторінки. На мобільній мережі кожен round trip додає 200–500 мс — сумарно до 2–3 секунд. Типовий сценарій: /users/{id}, /orders?userId={id}&limit=3, /notifications/unread, /recommendations?userId={id}, /loyalty/points/{id}. Клієнт повинен сам дочекатися всіх відповідей і виконати трансформацію. Це не тільки повільно, але й споживає зайвий трафік: завантаження непотрібних полів (наприклад, повної адреси при перегляді кошика) збільшує обсяг переданих даних на 30–50%. Економія на трафіку та інфраструктурі може досягати 40% після впровадження BFF. Ми пропонуємо впровадити проміжний шар Backend for Frontend (BFF).
BFF — це окремий бекенд-сервіс, створюваний під конкретний тип клієнта (веб, мобільний застосунок, Smart TV). Він приймає один запит від клієнта, паралельно звертається до необхідних мікросервісів, агрегує дані, відсікає зайве і повертає результат у форматі, оптимальному для даного клієнта. Концепція детально описана в статті Мартіна Фаулера Backend for frontend.
Які проблеми вирішує BFF?
- N+1 запит і затримки. Типова картина: 5–10 послідовних викликів для однієї сторінки. BFF скорочує це до одного виклику, виконуючи паралельні запити до сервісів. Економія часу — до 80% round trips.
- Надлишкові дані. Мікросервіс віддає поля, не потрібні клієнту (наприклад, адресу при перегляді кошика). BFF відсікає зайве, знижуючи обсяг переданих даних на 30–50%.
- Складна автентифікація. JWT, refresh token, httpOnly cookie — BFF керує сесіями централізовано, не розкриваючи доступ до сервісів з клієнта.
- Часткові збої. Якщо один сервіс недоступний, BFF може повернути часткову відповідь (null для фрагменту, що впав) замість помилки 500.
- Кешування спільних даних. Розміщення BFF між клієнтом і сервісами дозволяє кешувати агреговані відповіді (наприклад, рекомендації), знижуючи навантаження на мікросервіси на 40%.
Як ми реалізуємо BFF: стек і приклади
На практиці BFF зручно будувати на Node.js з Express або Apollo Server (GraphQL). У проектах ми використовуємо Node.js, TypeScript, Express або Apollo Server, Redis для кешування (ioredis), axios для HTTP-запитів.
Приклад для мобільного застосунку
Потрібен один ендпоінт /mobile/dashboard, який повертає профіль, останні замовлення, сповіщення та бали лояльності.
// mobile-bff/routes/dashboard.ts
router.get('/mobile/dashboard', authenticate, async (req, res) => {
const userId = req.user.id;
const [userResult, ordersResult, notificationsResult, loyaltyResult] =
await Promise.allSettled([
userService.get(`/users/${userId}`),
orderService.get(`/orders?customerId=${userId}&limit=3&fields=id,status,total,createdAt`),
notificationService.get(`/notifications/${userId}/unread-count`),
loyaltyService.get(`/loyalty/${userId}/summary`)
]);
const response = {
user: userResult.status === 'fulfilled' ? {
id: userResult.value.data.id,
name: userResult.value.data.displayName,
avatar: userResult.value.data.avatarUrl
} : null,
recentOrders: ordersResult.status === 'fulfilled'
? ordersResult.value.data.items.map(transformOrderForMobile)
: [],
unreadCount: notificationsResult.status === 'fulfilled'
? notificationsResult.value.data.count
: 0,
loyalty: loyaltyResult.status === 'fulfilled' ? {
points: loyaltyResult.value.data.balance,
tier: loyaltyResult.value.data.tier
} : null
};
res.json(response);
});
Приклад для веб-клієнта
Веб-клієнту потрібні ті самі дані, але з повним профілем, більшим списком замовлень та аналітикою.
// web-bff/routes/dashboard.ts
router.get('/web/dashboard', authenticate, async (req, res) => {
const userId = req.user.id;
const [user, orders, stats, notifications] = await Promise.allSettled([
userService.get(`/users/${userId}`),
orderService.get(`/orders?customerId=${userId}&limit=10`),
analyticsService.get(`/analytics/user/${userId}/stats`),
notificationService.get(`/notifications/${userId}?limit=5&unread=true`)
]);
res.json({
user: user.status === 'fulfilled' ? user.value.data : null,
orders: orders.status === 'fulfilled' ? orders.value.data : { items: [], total: 0 },
analytics: stats.status === 'fulfilled' ? stats.value.data : null,
notifications: notifications.status === 'fulfilled' ? notifications.value.data : []
});
});
Розгорнути приклад для GraphQL BFF
// web-bff/graphql/schema.ts
const typeDefs = gql`
type Query {
dashboard: Dashboard!
order(id: ID!): Order
}
type Dashboard {
user: User!
recentOrders: [Order!]!
stats: UserStats!
}
`;
const resolvers = {
Query: {
dashboard: async (_, __, { userId }) => {
const [user, orders, stats] = await Promise.all([
userService.getUser(userId),
orderService.getRecentOrders(userId),
analyticsService.getUserStats(userId)
]);
return { user, recentOrders: orders, stats };
}
}
};
Як реалізувати авторизацію та кешування в BFF?
BFF — природне місце для централізованої авторизації та кешування. JWT-токен перевіряється на рівні BFF, refresh token зберігається в httpOnly cookie (для веб-клієнта), а кеш у Redis прискорює відповіді для рідко змінюваних даних.
// authorization middleware
router.post('/auth/refresh', async (req, res) => {
const refreshToken = req.cookies.refresh_token;
if (!refreshToken) return res.status(401).json({ error: 'No token' });
const tokens = await authService.refreshTokens(refreshToken);
res.cookie('refresh_token', tokens.refreshToken, {
httpOnly: true, secure: true, sameSite: 'strict',
maxAge: 30 * 24 * 60 * 60 * 1000
});
res.json({ accessToken: tokens.accessToken });
});
// caching with Redis
import Redis from 'ioredis';
const redis = new Redis(process.env.REDIS_URL);
async function getCachedOrFetch<T>(key: string, ttl: number, fetcher: () => Promise<T>): Promise<T> {
const cached = await redis.get(key);
if (cached) return JSON.parse(cached);
const data = await fetcher();
await redis.setex(key, ttl, JSON.stringify(data));
return data;
}
Вибір між GraphQL і REST для BFF
Якщо клієнт — React-застосунок з Apollo Client, BFF може експортувати GraphQL-схему. Це дає клієнту можливість запитувати саме ті поля, які потрібні, без дублювання ендпоінтів. GraphQL BFF особливо зручний, коли вимоги до даних часто змінюються: клієнт сам контролює вибірку. Однак для простих мобільних застосунків з фіксованими екранами REST BFF часто виявляється ефективнішим через меншу складність.
Що входить у роботу
- Аудит поточної архітектури та виявлення частих round trips.
- Проектування BFF-шару для кожного клієнта (REST або GraphQL).
- Розробка API з агрегацією даних та трансформацією.
- Впровадження авторизації (JWT, session-based).
- Кешування з Redis або in-memory.
- Обробка помилок і partial failures (Promise.allSettled).
- Документація (OpenAPI або GraphQL SDL).
- Тестування та навантажувальне тестування.
- Деплой (Docker, Nginx, Vercel, AWS Lambda).
Терміни реалізації
| Тип BFF | Термін |
|---|---|
| REST BFF для 1 клієнта (3–5 ендпоінтів) | 1–2 тижні |
| GraphQL BFF + авторизація + кешування | 2–3 тижні |
| BFF для 2–3 клієнтів зі спільною бібліотекою | 3–4 тижні |
Процес роботи
- Аналітика — вивчаємо схему запитів і виділяємо вузькі місця.
- Проектування — визначаємо набір агрегованих ендпоінтів і стек.
- Реалізація — пишемо BFF-шар, кешування, авторизацію.
- Тестування — модульні, інтеграційні, performance-тести.
- Деплой — розгортання та налаштування моніторингу.
Типові помилки при впровадженні BFF
- Дублювання логіки — кожен BFF дублює трансформації. Рішення: винести спільні функції в shared library.
- Монолітний BFF — один BFF для всіх клієнтів призводить до тих самих проблем, що й єдиний API. Кожен клієнт — окремий BFF.
- Ігнорування partial failures — якщо один сервіс не відповідає, BFF не повинен падати. Використовуйте
Promise.allSettled. - Відсутність кешування — без кешу кожен запит долітає до сервісів, збільшуючи навантаження та час відповіді.
Чому BFF перевершує єдиний API?
Без BFF клієнт змушений самостійно агрегувати дані, що веде до надлишкових запитів і ускладнення клієнтської логіки. BFF бере на себе оркестрацію: один запит від клієнта → паралельне опитування мікросервісів → агрегація → трансформація → відповідь. Це прискорює завантаження, знижує трафік і спрощує підтримку.
Наш досвід
Ми впровадили BFF для великого e-commerce проєкту. Результати:
| Параметр | Без BFF | З BFF |
|---|---|---|
| Кількість запитів на екран | 7 | 1 |
| Час завантаження | 3.2 с | 0.8 с |
| Трафік на екран | 150 КБ | 80 КБ |
| Навантаження на сервіси | 100% | ~60% |
Досвід наших інженерів — 8+ років у мікросервісній архітектурі. Замовте розробку BFF під ключ і отримайте гарантію на час відповіді та відмовостійкість. Зв'яжіться з нами для безкоштовної консультації — оцінимо ваш проєкт за 1–2 дні. Замовте розробку BFF і отримайте оптимізацію під вашого клієнта.







