Comprensión del patrón Backend para Frontend (BFF): una guía sencilla

Comprensión del patrón Backend para Frontend (BFF): una guía sencilla

En una arquitectura de microservicios, nuestros sistemas se dividen en docenas de servicios pequeños y enfocados, como un Servicio de Usuario, un Servicio de Pedido y un Servicio de Producto.

Pero cuando se trata de mostrar esta información a los usuarios, diferentes dispositivos tienen necesidades muy diferentes. Un navegador web en una computadora de escritorio de alta velocidad necesita un panel completo lleno de tablas, barras laterales y gráficos. Una aplicación móvil en una red celular lenta necesita un diseño simple y liviano para ahorrar ancho de banda y batería. Es posible que una aplicación de reloj inteligente solo necesite una línea de texto.

Si todas estas interfaces consultan exactamente la misma API de backend, alguien tiene que comprometerse. O la aplicación móvil se ve obligada a descargar cantidades masivas de datos inútiles, o la aplicación web se ve obligada a realizar docenas de solicitudes de red independientes para obtener todo lo que necesita.

Este es exactamente el problema resuelto por el Patrón Backend para Frontend (BFF). En esta guía, explicaremos este patrón en palabras simples, veremos una analogía del mundo real, la compararemos con una API Gateway estándar y recorreremos una implementación práctica de código.


La analogía del mundo real: el menú del restaurante

Imaginemos un restaurante que atiende a tres tipos de comensales muy diferentes:

  1. Un crítico gastronómico que quiere un menú de degustación completo de cinco platos con listas detalladas de ingredientes.
  2. Un viajero ocupado que quiere un refrigerio rápido y empaquetado para comer en el tren.
  3. Un niño que quiere una comida infantil sencilla, con porciones pequeñas y sin ingredientes picantes.

Si el restaurante solo tuviera un menú único que enumerara las tres opciones con todo detalle, sería abrumador. El viajero perdería el tiempo leyendo recetas de cinco platos y los padres del niño tendrían dificultades para encontrar opciones de comida sencillas.

En cambio, el restaurante imprime tres menús personalizados: un menú de degustación, un menú exprés para llevar y un menú para niños.

Cada menú se basa en la misma cocina (los microservicios), pero formatea y dimensiona las opciones específicamente para ese cliente (el cliente).

En este escenario:

  • La cocina representa tus microservicios (Usuario, Catálogo, Pago).
  • Los menús personalizados son tus BFF (Web BFF, Mobile BFF, Watch BFF).
  • Los comensales son tus interfaces (navegador de escritorio, aplicación móvil, reloj inteligente).

El problema: la API “talla única”

Cuando los microservicios se hicieron populares por primera vez, muchos equipos crearon una puerta de enlace API única y compartida para manejar todos los clientes frontend:

Diagrama de arquitectura de backend para frontend (BFF) que compara flujos web y móviles

Si bien un único punto de entrada es fantástico, una API compartida introduce varios obstáculos a la hora de escalar:

  • Payload Bloat para dispositivos móviles: la aplicación web de escritorio necesita el historial de pedidos, la dirección de facturación, la imagen de perfil y los puntos de fidelidad del usuario. La aplicación móvil solo necesita mostrar “Último pedido: enviado”. Con una API compartida, la aplicación móvil descarga toda la carga útil del perfil, desperdiciando datos valiosos y ralentizando los tiempos de carga.
  • Cuellos de botella de API: un solo equipo se convierte en el cuello de botella para la puerta de enlace compartida. Si el equipo de iOS quiere cambiar un pequeño campo de diseño, debe esperar a que el equipo de la puerta de enlace compartida implemente una nueva versión, lo que ralentiza los ciclos de desarrollo.
  • Diferentes necesidades de seguridad: un navegador web puede requerir sesiones basadas en cookies para evitar secuencias de comandos entre sitios (XSS), mientras que una aplicación móvil prefiere encabezados OAuth basados ​​en tokens. Manejar ambos en un solo servidor crea un código complejo y desordenado.

La solución: el patrón BFF

En lugar de crear una puerta de enlace gigante para todos los dispositivos, el Patrón BFF aboga por construir un servidor backend dedicado para cada aplicación frontend.

Tendrás:

  • Web BFF: Maneja solicitudes desde el navegador de escritorio. Agrega perfiles completos, catálogos de productos e información de pago detallada.
  • Mobile BFF: maneja solicitudes de aplicaciones de iOS y Android. Agrega datos, filtra campos innecesarios y comprime la respuesta final para garantizar un rendimiento rápido.

API Gateway frente a BFF: ¿Cuál es la diferencia?

Es común confundir estos dos patrones porque ambos se ubican entre el cliente y los microservicios. Aquí está la distinción:

Característica Puerta de enlace API general Backend para Frontend (BFF)
Número de puertas de enlace Normalmente uno para todo el sistema. Múltiples (uno para cada tipo de dispositivo cliente).
Responsabilidad Enrutamiento de alto nivel, limitación de velocidad y seguridad global. Agregar datos y adaptar cargas útiles para una interfaz específica.
Propiedad Administrado por un equipo de infraestructura de plataforma/backend dedicado. Administrado por el equipo frontend que crea la aplicación correspondiente.
Personalización Bajo. Los cambios afectan a todos los clientes. Alto. Los cambios sólo afectan a una aplicación cliente.

Una implementación práctica (Node.js/Express)

Para entender cómo funciona esto en la práctica, escribamos un ejemplo sencillo de Node.js.

Imaginemos que tenemos dos microservicios ejecutándose internamente:

  • Servicio de usuario (devuelve información básica del perfil del usuario)
  • Servicio de pedidos (devuelve una lista de pedidos con todos los detalles)

Queremos crear un BFF web y un BFF móvil para servir nuestro sitio de escritorio y nuestra aplicación móvil de manera diferente.

1. El simulacro de microservicios compartidos

Primero, aquí están los datos simulados de nuestros dos microservicios subyacentes:

// Internal User Service Response
const userProfile = {
    id: 42,
    username: "dev_coder",
    email: "coder@ghaznix.com",
    avatarUrl: "https://ghaznix.com/avatars/42.png",
    preferences: { theme: "light", newsletter: true }
};

// Internal Order Service Response
const orderHistory = [
    { id: "ORD-99", date: "2026-06-25", items: ["Laptop", "Mouse"], status: "Shipped", tax: 15.00, total: 1215.00 },
    { id: "ORD-88", date: "2026-05-12", items: ["Keyboard"], status: "Delivered", tax: 5.00, total: 105.00 }
];

2. The Web BFF (devuelve la carga útil detallada completa)

Web BFF agrega todos los campos porque la pantalla del escritorio tiene mucho espacio para mostrarlos:

const express = require('express');
const webBff = express();

webBff.get('/dashboard', (req, res) => {
    // Web needs everything: profile + full order details + settings
    const responsePayload = {
        user: {
            username: userProfile.username,
            email: userProfile.email,
            avatar: userProfile.avatarUrl,
            theme: userProfile.preferences.theme
        },
        orders: orderHistory // Send all order details, taxes, and items
    };
    
    res.json(responsePayload);
});

webBff.listen(3001, () => console.log('Web BFF running on port 3001'));

3. El mejor amigo móvil (devoluciones minimizadas, carga útil agregada)

Mobile BFF filtra campos innecesarios (como correo electrónico, configuración e impuestos) y agrega los elementos del pedido para ahorrar ancho de banda:

const express = require('express');
const mobileBff = express();

mobileBff.get('/dashboard', (req, res) => {
    // Mobile only wants: username, avatar, and summary of the latest order
    const latestOrder = orderHistory[0];
    
    const responsePayload = {
        user: {
            username: userProfile.username,
            avatar: userProfile.avatarUrl
        },
        latestOrderStatus: {
            orderId: latestOrder.id,
            status: latestOrder.status,
            date: latestOrder.date,
            itemCount: latestOrder.items.length // Send count instead of array list
        }
    };
    
    res.json(responsePayload);
});

mobileBff.listen(3002, () => console.log('Mobile BFF running on port 3002'));

Comparación del tamaño de la carga útil

  • Tamaño de respuesta de Web BFF: Contiene configuración anidada, preferencias, lista completa de pedidos, impuestos, artículos, etc. (Aprox. 400 bytes).
  • Tamaño de respuesta de BFF móvil: Contiene solo 6 pares clave-valor que representan lo esencial. (Aprox. 120 bytes: ¡reducción del 70% en el tamaño de la red!).

Pros y contras del patrón BFF

Si bien es muy eficaz, el patrón BFF tiene sus ventajas y desventajas:

Ventaja (Pro) Desventaja (Con)
Rendimiento optimizado del cliente: los clientes solo cargan los datos exactos que necesitan, lo que reduce el consumo de batería y el uso de memoria. Duplicación de código: podría terminar escribiendo una lógica de recuperación de datos similar en varias bases de código BFF.
Ciclos de lanzamiento más rápidos: el equipo de interfaz móvil puede actualizar su servidor BFF sin necesidad de coordinarse con los desarrolladores web. Aumento del número de servidores: en lugar de administrar una puerta de enlace API, ahora debe implementar y administrar varios servicios BFF.
Código de interfaz simplificado: el cliente no necesita manejar una lógica compleja de clasificación, filtrado o combinación; simplemente muestra el JSON que recibe. Gestión de seguridad: las certificaciones SSL/TLS, las reglas de límite de velocidad y los firewalls se deben administrar en múltiples puertas de enlace.

Conclusión

El patrón Backend for Frontend (BFF) es una poderosa arquitectura para sistemas que atienden a múltiples tipos de clientes, como dispositivos web, móviles y de IoT. Al crear puertas de enlace personalizadas para cada interfaz específica, desacopla el desarrollo del cliente, minimiza el tamaño de la carga útil y ofrece una experiencia de usuario más rápida y con mayor capacidad de respuesta.

Si su sistema solo tiene una aplicación web, una puerta de enlace API compartida es suficiente. Pero en el momento en que comienza a crear aplicaciones móviles o experiencias de dispositivos especializadas junto con su aplicación web, implementar un BFF es la mejor manera de mantener sus arquitecturas frontend y backend limpias, optimizadas e independientes.


Explore más conocimientos sobre desarrollo de software e ingeniería backend en el Blog de Ghaznix →