Introduction
Backend for Frontend (BFF) is a pattern that places a separate backend layer for each frontend client. BFF aggregates data from multiple microservices, transforming it into a format suitable for the specific frontend.

1. Why do you need a BFF?
1.1 The problem of not having a BFF
❌ Mỗi MFE gọi trực tiếp nhiều microservices:
Product MFE ──► Product Service
──► Review Service
──► Inventory Service
──► Pricing Service
→ 4 API calls cho 1 product page
→ Frontend phải aggregate data
→ Over-fetching (mỗi API trả về nhiều hơn cần)
→ Latency: waterfall requests
1.2 With BFF
✅ BFF aggregates cho frontend:
Product MFE ──► Web BFF ──► Product Service
──► Review Service
──► Inventory Service
→ 1 API call cho 1 product page
→ BFF aggregate và transform data
→ Frontend nhận đúng data cần
→ Parallel calls tại BFF layer
2. BFF Architecture
┌─────────────┐ ┌─────────────┐ ┌─────────────┐
│ Web App │ │ Mobile App │ │ Admin App │
│ (MFE) │ │ (React │ │ (MFE) │
│ │ │ Native) │ │ │
└──────┬──────┘ └──────┬──────┘ └──────┬──────┘
│ │ │
▼ ▼ ▼
┌──────────────┐ ┌──────────────┐ ┌──────────────┐
│ Web BFF │ │ Mobile BFF │ │ Admin BFF │
│ (Node.js) │ │ (Node.js) │ │ (Node.js) │
│ Full data │ │ Compact data│ │ All CRUD │
└──────┬───────┘ └──────┬───────┘ └──────┬───────┘
│ │ │
└────────────────┼────────────────┘
▼
┌─────────────────┐
│ Microservices │
│ (gRPC / REST) │
└─────────────────┘
3. BFF Design Principles
3.1 One BFF per Frontend Type
| Frontend | BFF | Optimized for |
|---|---|---|
| Web (Desktop) | Web BFF | Full data, rich UI |
| Mobile | Mobile BFF | Compact data, bandwidth |
| Admin Panel | Admin BFF | CRUD operations |
| Third-party | Public API (not BFF) | Stable, versioned |
3.2 BFF Responsibilities
BFF SHOULD:
✅ Aggregate data từ multiple services
✅ Transform data cho frontend format
✅ Handle authentication (validate tokens)
✅ Caching (Redis) cho frequently accessed data
✅ Rate limiting per client
BFF SHOULD NOT:
❌ Contain business logic (belongs to services)
❌ Have its own database (stateless!)
❌ Become a "smart proxy" monolith
❌ Be shared across different frontends
4. BFF Implementation (Node.js/Fastify)
// Web BFF - Product Page Aggregation
app.get('/api/bff/product/:id', async (req, reply) => {
const { id } = req.params;
// Parallel calls to microservices
const [product, reviews, inventory] = await Promise.all([
productService.getProduct(id),
reviewService.getReviews(id, { limit: 5 }),
inventoryService.getStock(id),
]);
// Transform for web frontend
return {
...product,
rating: reviews.averageRating,
topReviews: reviews.items.slice(0, 3),
inStock: inventory.quantity > 0,
stockLevel: inventory.quantity > 10 ? 'high' : 'low',
};
});
5. BFF vs API Gateway
| Features | API Gateway | BFF |
|---|---|---|
| Purpose | Cross-cutting concerns | Frontend-specific aggregation |
| Logic | Routing, auth, rate limit | Data transformation |
| Per client | One for all | One per frontend type |
| Maintained by | Platform team | Frontend team |
In practice, use both:
Frontend → API Gateway → BFF → Microservices
(routing, (aggregation,
auth, transformation)
rate limit)
Summary
- BFF = separate backend for each frontend type
- Aggregates data, transforms format, reduces frontend complexity
- Stateless, does not contain business logic
- One BFF per frontend type (Web, Mobile, Admin)
- Often combined with API Gateway
Next article: Lesson 18: API Gateway — Kong, APISIX & Envoy