0
0
MicroservicesConceptBeginner · 4 min read

Backend for Frontend Pattern: What It Is and When to Use

The Backend for Frontend (BFF) pattern creates a dedicated backend service for each user interface or client type. It acts as a tailored middle layer that simplifies and optimizes communication between the frontend and multiple backend services.
⚙️

How It Works

Imagine you have different types of users accessing your app: a web browser, a mobile app, and maybe a smart TV app. Each of these clients needs data in a slightly different way. Instead of making each client talk directly to many backend services, the Backend for Frontend (BFF) pattern creates a special backend just for each client type.

This BFF acts like a personal assistant who knows exactly what the client needs. It gathers data from various backend services, combines it, and sends back only what the client requires. This makes the frontend simpler and faster because it gets exactly the right data in the right format.

Think of it like ordering food: instead of going to multiple kitchens yourself, you have a waiter (the BFF) who collects all your dishes and brings them to your table ready to eat.

💻

Example

This example shows a simple BFF service in Node.js using Express. It fetches user info and order data from two backend services and combines them for a mobile app client.

javascript
import express from 'express';
import fetch from 'node-fetch';

const app = express();
const PORT = 3000;

// Simulated backend service URLs
const USER_SERVICE_URL = 'https://api.example.com/users';
const ORDER_SERVICE_URL = 'https://api.example.com/orders';

app.get('/mobile/user-dashboard', async (req, res) => {
  try {
    const userId = req.query.userId;
    // Fetch user info
    const userResponse = await fetch(`${USER_SERVICE_URL}/${userId}`);
    const user = await userResponse.json();

    // Fetch user orders
    const ordersResponse = await fetch(`${ORDER_SERVICE_URL}?userId=${userId}`);
    const orders = await ordersResponse.json();

    // Combine data tailored for mobile client
    const dashboardData = {
      name: user.name,
      recentOrders: orders.slice(0, 3),
      notifications: user.notifications || []
    };

    res.json(dashboardData);
  } catch (error) {
    res.status(500).json({ error: 'Failed to fetch dashboard data' });
  }
});

app.listen(PORT, () => {
  console.log(`BFF server running on port ${PORT}`);
});
Output
BFF server running on port 3000
🎯

When to Use

Use the Backend for Frontend pattern when you have multiple client types (web, mobile, IoT) that need different data shapes or workflows. It helps keep frontend code simple and reduces the number of calls each client makes.

It is especially useful when backend services are shared and complex, and you want to avoid exposing all backend details to every client. For example, a mobile app might need less data or a different format than a web app.

Real-world use cases include large e-commerce sites, social media platforms, or any system with diverse user interfaces needing optimized data delivery.

Key Points

  • The BFF pattern creates a backend service dedicated to each frontend client.
  • It simplifies frontend logic by tailoring data and APIs per client.
  • Helps reduce over-fetching or under-fetching of data.
  • Improves performance and user experience by optimizing data delivery.
  • Useful in microservices where backend APIs are shared but clients differ.

Key Takeaways

Backend for Frontend creates a custom backend layer for each client type to simplify frontend data needs.
It reduces complexity by tailoring API responses to what each client requires.
Use BFF when multiple clients need different data formats or workflows from shared backend services.
BFF improves performance by minimizing unnecessary data transfer and calls.
It acts as a middleman that combines and adapts backend data for each frontend.