Skip to content
IRC-CodingIRC-Coding
API Gateway PatternsBackend for FrontendBFFAPI CompositionProtocol TranslationAgregaciónCircuit BreakerStrangler FigMicroservices

API Gateway Patterns: BFF, Composición y Traducción

Patrones API Gateway explicados: BFF, composición, traducción de protocolos, Circuit Breaker y agregación con ejemplos de código.

S

schutzgeist

14 min read
API Gateway Patterns: BFF, Composición y Traducción

Patrones de API Gateway: Backend for Frontend, Composición, Agregación y más

Los patrones de API Gateway son patrones arquitectónicos probados que se implementan en el gateway para abstraer la complejidad de los clientes, mejorar el rendimiento y orquestar microservicios. Conocer estos patrones permite tomar decisiones arquitectónicas fundamentadas.

¿Qué son los patrones de API Gateway?

Los patrones de API Gateway son patrones arquitectónicos que utilizan el API Gateway como punto central para resolver problemas recurrentes en la arquitectura de APIs. Definen cómo el gateway transforma, agrega, redirige y asegura las solicitudes, sin que los clientes ni los backends necesiten implementar esta lógica por sí solos.

Los patrones más importantes:

  1. Backend for Frontend (BFF): Un gateway especializado por tipo de cliente
  2. API Composition / Aggregation: Múltiples llamadas a backend en una sola solicitud
  3. Protocol Translation: Conversión de protocolo en el gateway
  4. Circuit Breaker: Protección contra fallos en cascada
  5. Strangler Fig: Migración gradual de APIs antiguas
  6. API Versioning: Versionado y versiones de API en paralelo
  7. Request/Response Transformation: Adaptación de payloads en el gateway

¿Quién utiliza los patrones de API Gateway?

  • Arquitectos de software eligen patrones en función de los requisitos
  • Equipos de plataforma implementan patrones como configuración del gateway
  • Desarrolladores backend necesitan entender cómo el gateway transforma sus endpoints
  • Desarrolladores frontend se benefician de respuestas agregadas y adaptadas

¿Por qué es importante este tema en informática y en exámenes?

Los patrones de API Gateway son conocimientos fundamentales para certificaciones de arquitectura (AWS Solutions Architect, Azure Solutions Architect) y se tratan en detalle en libros sobre microservicios (Sam Newman, Chris Richardson). En exámenes de IHK y en estudios de informática, patrones como BFF y Circuit Breaker se preguntan como ejemplos de patrones de diseño a nivel arquitectónico. Comprender estos patrones es esencial para diseñar landscapes de APIs escalables y mantenibles.

Conceptos clave en detalle

1. Backend for Frontend (BFF)

El patrón BFF establece que cada tipo de cliente obtiene su propio gateway (o su propia configuración de gateway) ajustado exactamente a sus necesidades.

El problema: una aplicación web, una aplicación móvil y un cliente B2B tienen requisitos diferentes. La aplicación web necesita datos completos para UIs complejas. La aplicación móvil necesita datos reducidos para redes lentas. El cliente B2B necesita endpoints de lote y XML. Un único gateway no puede satisfacer óptimamente todos estos requisitos.

La solución: tres BFFs:

  • Web-BFF: Respuestas completas, agregaciones complejas, CORS
  • Mobile-BFF: Campos reducidos, jerarquías planas, caché, límites de velocidad inferiores
  • B2B-BFF: Endpoints de lote, transformación XML, mTLS, cuotas superiores

Cada BFF puede desarrollarse, desplegarse y escalarse de forma independiente.

2. API Composition / Aggregation

El patrón de composición agrupa múltiples solicitudes a backends en una única solicitud de cliente. El cliente envía una solicitud al gateway, el gateway llama a varios backends en paralelo y combina los resultados.

Ejemplo: un cliente llama a /api/dashboard. El gateway llama en paralelo a:

  • /users/42 (User Service)
  • /orders?userId=42 (Order Service)
  • /notifications?userId=42 (Notification Service)

El gateway combina las tres respuestas en una única respuesta JSON. El cliente realiza un viaje redondo en lugar de tres.

Ventajas: latencia reducida (llamadas paralelas), complejidad de cliente reducida, manejo de errores centralizado. Desventajas: el gateway se vuelve más complejo, el manejo de errores ante fallos parciales es difícil.

3. Protocol Translation

El gateway convierte protocolos entrantes en protocolos internos:

  • REST a gRPC: Los clientes externos envían REST, el gateway convierte a gRPC para microservicios internos. gRPC es más eficiente (Protobuf, HTTP/2), pero menos accesible para clientes externos.
  • SOAP a REST: Los servicios SOAP heredados se ofrecen como APIs REST modernas hacia afuera.
  • HTTP a WebSocket: El gateway mantiene conexiones WebSocket y se comunica internamente sobre HTTP.
  • GraphQL a REST: El gateway acepta queries GraphQL y las mapea a llamadas a backends REST.

4. Circuit Breaker

El Circuit Breaker protege el sistema contra fallos en cascada. Tiene tres estados:

  • Closed: Las solicitudes se redirigen normalmente. Los errores se cuentan.
  • Open: A partir de un umbral de tasa de errores (p. ej., 50% en 10 segundos), todas las solicitudes se rechaza de inmediato con una respuesta de error. El backend ya no se sobrecarga.
  • Half-Open: Después de un período de espera (p. ej., 30 segundos), se permite una solicitud de prueba. Si tiene éxito, el breaker vuelve a Closed. Si falla, permanece Open.

El patrón evita que un servicio lento o caído bloquee todo el sistema, porque los clientes esperan timeouts.

5. Strangler Fig

El patrón Strangler Fig permite la migración gradual de una API antigua a una nueva arquitectura. Recibe su nombre de la higuera estranguladora, que crece lentamente alrededor de un árbol y lo reemplaza.

El proceso:

  1. El gateway redirige todas las solicitudes a la API antigua (Facade).
  2. Los nuevos endpoints se implementan en el nuevo sistema. El gateway redirige estos al nuevo sistema.
  3. Gradualmente se migran más endpoints.
  4. Cuando se han migrado todos los endpoints, se apaga la API antigua.

Ventaja: migración sin lanzamiento de Big-Bang, recuperable, de bajo riesgo.

6. API Versioning en el Gateway

El gateway gestiona múltiples versiones de API en paralelo:

  • /v1/users -> servicio de usuario antiguo (Legacy)
  • /v2/users -> nuevo servicio de usuario (con campos extendidos)

El gateway puede mapear versiones: una solicitud v1 se transforma para que funcione también en el backend v2 (Forward Compatibility). O el gateway redirige v1 al backend antiguo y v2 al nuevo.

7. Request/Response Transformation

El gateway transforma payloads sin cambiar el backend:

  • Reducción de campos: el cliente móvil recibe solo 5 campos en lugar de 20
  • Renombramiento de campos: first_name (externo) a firstName (interno)
  • Conversión de formato: XML a JSON, snake_case a camelCase
  • Enriquecimiento de headers: headers de seguridad, correlation ID, tenant ID
  • Filtrado de respuestas: eliminar campos sensibles para determinados clientes

¿Por qué son importantes los patrones de API Gateway en la práctica?

Escenario 1: Rendimiento de aplicación móvil

Una aplicación móvil necesita 3 llamadas API para una pantalla de dashboard. Cada llamada tiene 200ms de latencia. Total: 600ms más renderizado. Con API Composition: 1 llamada, llamadas a backend en paralelo, total: 250ms. La aplicación se siente notablemente más rápida.

Escenario 2: Migración de legacy

Un monolito de 10 años debe migrarse a microservicios. Un lanzamiento de Big-Bang es demasiado riesgoso. Con el patrón Strangler Fig, los endpoints se migran uno a uno, el gateway redirige automáticamente al sistema correcto. Los clientes antiguos no notan nada de la migración.

Escenario 3: Prevenir fallas en cascada

El servicio A llama al servicio B, que está lento. El servicio A espera a que expire el timeout mientras ocupa threads. Múltiples solicitudes se acumulan y el servicio A también se vuelve lento. El Circuit Breaker en el gateway detecta los errores del servicio B, abre el circuito, y el servicio A recibe inmediatamente una respuesta de error en lugar de esperar. El sistema permanece estable.

Ejemplo práctico: Kong API Gateway con Composition y Circuit Breaker

Este ejemplo muestra dos patrones en la práctica: API Composition (un endpoint agrega múltiples llamadas a backends) y Circuit Breaker (protección contra fallos de backends). Se eligió porque estos dos patrones son los más comunes en la práctica y resuelven el mayor problema arquitectónico: complejidad del cliente y resistencia a fallos.

# kong-patterns.yml
# API Gateway Patterns: Composition + Circuit Breaker + BFF

services:
  # --- Backend Services ---
  - name: user-service
    url: http://user-service.internal:3000

  - name: order-service
    url: http://order-service.internal:3001

  - name: notification-service
    url: http://notification-service.internal:3002

  # --- BFF: Mobile (datos reducidos) ---
  - name: mobile-bff
    url: http://bff-mobile.internal:4000
    routes:
      - name: mobile-dashboard
        paths:
          - /mobile/dashboard
        strip_path: false

  # --- BFF: Web (datos completos) ---
  - name: web-bff
    url: http://bff-web.internal:4001
    routes:
      - name: web-dashboard
        paths:
          - /web/dashboard
        strip_path: false

routes:
  # --- Composition Route: /dashboard agrega 3 servicios ---
  - name: dashboard-composite
    paths:
      - /api/dashboard
    strip_path: false
    service: user-service  # Fallback, sobrescrito por plugin

plugins:
  # --- Circuit Breaker para todos los servicios ---
  - name: request-termination
    service: order-service
    config:
      status_code: 503
      message: "Order Service temporarily unavailable"

  # --- Rate Limiting por BFF ---
  - name: rate-limiting
    route: mobile-dashboard
    config:
      minute: 60
      limit_by: ip

  - name: rate-limiting
    route: web-dashboard
    config:
      minute: 200
      limit_by: consumer
// bff-composition.js
// Backend for Frontend: Dashboard Composition con Circuit Breaker
// Node.js/Express — agrega User, Orders y Notifications

const express = require('express');
const axios = require('axios');
const CircuitBreaker = require('opossum');

const app = express();

// Circuit Breaker para cada servicio
const userBreaker = new CircuitBreaker(async (userId) => {
  const res = await axios.get(`http://user-service.internal:3000/users/${userId}`, {
    timeout: 2000
  });
  return res.data;
}, {
  timeout: 3000,
  errorThresholdPercentage: 50,
  resetTimeout: 30000
});

const orderBreaker = new CircuitBreaker(async (userId) => {
  const res = await axios.get(`http://order-service.internal:3001/orders?userId=${userId}`, {
    timeout: 2000
  });
  return res.data;
}, {
  timeout: 3000,
  errorThresholdPercentage: 50,
  resetTimeout: 30000
});

const notificationBreaker = new CircuitBreaker(async (userId) => {
  const res = await axios.get(`http://notification-service.internal:3002/notifications?userId=${userId}`, {
    timeout: 2000
  });
  return res.data;
}, {
  timeout: 3000,
  errorThresholdPercentage: 50,
  resetTimeout: 30000
});

// Funciones fallback cuando el circuito está abierto
userBreaker.fallback(() => ({ id: null, name: 'Unbekannt', error: 'User Service unavailable' }));
orderBreaker.fallback(() => ({ orders: [], error: 'Order Service unavailable' }));
notificationBreaker.fallback(() => ({ notifications: [], error: 'Notification Service unavailable' }));

// Endpoint de composition: /api/dashboard?userId=42
app.get('/api/dashboard', async (req, res) => {
  const userId = req.query.userId;
  if (!userId) {
    return res.status(400).json({
      error: 'MISSING_PARAMETER',
      message: 'userId ist erforderlich'
    });
  }

  // Llamadas paralelas con Circuit Breaker
  const [user, orders, notifications] = await Promise.all([
    userBreaker.fire(userId),
    orderBreaker.fire(userId),
    notificationBreaker.fire(userId)
  ]);

  // Respuesta agregada
  res.json({
    user: user,
    orders: orders.orders || [],
    orderCount: orders.orders ? orders.orders.length : 0,
    notifications: notifications.notifications || [],
    unreadNotifications: notifications.notifications
      ? notifications.notifications.filter(n => !n.read).length
      : 0,
    // Indicador de fallos parciales
    _meta: {
      userAvailable: !user.error,
      ordersAvailable: !orders.error,
      notificationsAvailable: !notifications.error,
      timestamp: new Date().toISOString()
    }
  });
});

// Mobile BFF: Campos reducidos
app.get('/mobile/dashboard', async (req, res) => {
  const userId = req.query.userId;
  const [user, orders, notifications] = await Promise.all([
    userBreaker.fire(userId),
    orderBreaker.fire(userId),
    notificationBreaker.fire(userId)
  ]);

  // Mobile: Solo campos esenciales, estructura plana
  res.json({
    userName: user.name || 'Unbekannt',
    orderCount: orders.orders ? orders.orders.length : 0,
    unreadCount: notifications.notifications
      ? notifications.notifications.filter(n => !n.read).length
      : 0
  });
});

// Web BFF: Datos completos
app.get('/web/dashboard', async (req, res) => {
  const userId = req.query.userId;
  const [user, orders, notifications] = await Promise.all([
    userBreaker.fire(userId),
    orderBreaker.fire(userId),
    notificationBreaker.fire(userId)
  ]);

  // Web: Todos los campos, estructura anidada
  res.json({
    profile: user,
    recentOrders: orders.orders || [],
    allNotifications: notifications.notifications || [],
    _meta: {
      userAvailable: !user.error,
      ordersAvailable: !orders.error,
      notificationsAvailable: !notifications.error
    }
  });
});

app.listen(4000, () => {
  console.log('BFF listening on port 4000');
});

Información detallada

BFF: Cuándo y cuántos necesitas

Regla general: un BFF por tipo de cliente, no por dispositivo. Los BFFs típicos son:

  • Web-BFF: Aplicaciones de navegador (SPA, SSR)
  • Mobile-BFF: Aplicaciones iOS/Android
  • B2B-BFF: Integraciones con socios

No recomendado: un BFF por pantalla o por feature. Esto lleva a una explosión de BFFs y sobrecarga de mantenimiento.

Composition: Síncrona vs. Asíncrona

La composition que se muestra es síncrona (el cliente espera la respuesta). Para composition asíncrona hay dos variantes:

  • Request/Reply con WebSocket: El cliente se suscribe al gateway, que llamará a los backends y empujará los resultados tan pronto como estén disponibles.
  • Event-Driven: El cliente envía una solicitud, el gateway inicia el procesamiento asíncrono y devuelve un ID de correlación. El cliente consulta o se suscribe al resultado.

Configuración de Circuit Breaker

Parámetros importantes:

  • errorThresholdPercentage: Con qué porcentaje de errores se abre el breaker (típicamente: 50%)
  • resetTimeout: Cuánto tiempo permanece abierto el breaker (típicamente: 30s)
  • timeout: Cuándo se considera que una llamada ha fallado (típicamente: 2-5s)
  • volumeThreshold: Número mínimo de llamadas antes de calcular la tasa de errores (típicamente: 5)

Strangler Fig: Riesgos y medidas preventivas

  • Lógica duplicada: Durante la migración existe lógica tanto en el sistema antiguo como en el nuevo. Medida preventiva: librerías compartidas para la lógica de negocio.
  • Errores de enrutamiento: El gateway dirige las solicitudes al sistema equivocado. Medida preventiva: feature flags y canary releases.
  • Consistencia de datos: El sistema antiguo y el nuevo utilizan la misma base de datos o diferentes. Medida preventiva: particionamiento claro de datos o sincronización de modelos de lectura.

Transformación: JSONPath y Templates

Los gateways API modernos soportan transformaciones con JSONPath o templates:

  • JSONPath: $.user.first_name extrae un campo
  • JQ: transformaciones complejas con sintaxis jq
  • Liquid Templates: motor de plantillas para transformación de respuestas (Azure API Management)
  • Lua: Kong/OpenResty permite scripts Lua para transformaciones complejas

Anti-patrones

  • Gateway como capa de lógica de negocio: El gateway no debe contener lógica de negocio. Transformación y agregación sí, pero no cálculos o validaciones de dominio.
  • Demasiados BFFs: Cada equipo quiere su propio BFF. Esto causa duplicación y sobrecarga de mantenimiento.
  • Composición sin timeout: Si un backend es lento, el cliente espera indefinidamente. Cada llamada de composición necesita un timeout.
  • Circuit Breaker sin fallback: Sin fallback el cliente recibe un mensaje de error críptico. Define respuestas de fallback significativas.

FAQ: API Gateway Patterns

1. ¿Qué es el patrón Backend for Frontend (BFF)?

BFF significa que cada tipo de cliente (web, mobile, B2B) obtiene su propio gateway API o su propia configuración de gateway, ajustada exactamente a sus necesidades. El BFF web entrega datos completos, el BFF mobile campos reducidos, el BFF B2B endpoints por lotes. Cada BFF se puede desarrollar e implementar de forma independiente.

2. ¿Qué es la composición de API?

La composición de API (o agregación) significa que el gateway divide una solicitud del cliente en varias solicitudes backend, recopila los resultados y los devuelve como una sola respuesta. El cliente realiza un roundtrip en lugar de varios. Esto reduce la latencia (llamadas paralelas) y la complejidad del cliente.

3. ¿Qué es la traducción de protocolos en el gateway API?

La traducción de protocolos significa que el gateway convierte un protocolo entrante a otro. Por ejemplo, las solicitudes REST de clientes externos se reenvían internamente como gRPC, o los servicios heredados SOAP se ofrecen como REST hacia el exterior. Esto permite que los clientes externos usen protocolos simples mientras se utilizan protocolos eficientes internamente.

4. ¿Cómo funciona un Circuit Breaker?

Un Circuit Breaker tiene tres estados: Closed (las solicitudes se reenvían, se cuentan los errores), Open (a partir del umbral de errores todas las solicitudes se rechazan inmediatamente, el backend se protege) y Half-Open (después del tiempo de espera se intenta una solicitud de prueba). Esto previene fallos en cascada cuando los backends son lentos o están caídos.

5. ¿Qué es el patrón Strangler Fig?

El patrón Strangler Fig permite migrar gradualmente una API antigua. El gateway reenvía inicialmente todas las solicitudes al sistema antiguo. Los nuevos endpoints se implementan en el nuevo sistema y el gateway los enruta ahí. Poco a poco se migran todos los endpoints. Una vez completada la migración, se apaga el sistema antiguo.

6. ¿Cuántos BFFs deberías tener?

Regla general: un BFF por tipo de cliente, no por dispositivo o característica. Lo típico son tres BFFs: web (aplicaciones de navegador), mobile (iOS/Android) e integraciones B2B con partners. Más BFFs causan duplicación y sobrecarga de mantenimiento. Menos BFFs fuerzan clientes diferentes a usar la misma forma.

7. ¿Qué sucede en la composición si un backend falla?

Ante un fallo backend el gateway debe entregar valores de fallback y marcar la respuesta con metadatos (por ejemplo, _meta.ordersAvailable: false). El cliente recibe una respuesta parcial en lugar de un error. El Circuit Breaker previene esperar a timeouts. La respuesta parcial permite degradación elegante en el cliente.

8. ¿Debería el gateway contener lógica de negocio?

No, el gateway no debe contener lógica de negocio. Puede asumir transformación, agregación, autenticación y enrutamiento, pero no cálculos o validaciones de dominio. La lógica de negocio en el gateway causa código difícil de probar, dependencias entre equipos y degradación de la arquitectura.

9. ¿Cuál es la diferencia entre composición síncrona y asíncrona?

Composición síncrona: el cliente espera la respuesta agregada. Composición asíncrona: el cliente envía la solicitud, recibe un ID de correlación y después consulta o se suscribe para el resultado. Asíncrona es mejor para agregaciones de larga duración, síncrona para llamadas paralelas rápidas.

10. ¿Cómo configuras correctamente un Circuit Breaker?

Parámetros importantes: errorThresholdPercentage (típicamente 50%, a partir de cuándo se abre el breaker), resetTimeout (típicamente 30s, cuánto tiempo permanece abierto), timeout (típicamente 2-5s, cuándo una llamada se considera error) y volumeThreshold (típicamente 5, mínimo de llamadas antes de calcular la tasa de errores). Los valores dependen del servicio. Los servicios críticos necesitan breakers más rápidos.

11. ¿Qué es la transformación de solicitud/respuesta?

Transformación significa que el gateway adapta las payloads sin cambiar el backend. Ejemplos: reducir campos para clientes mobile, renombrar campos (snake_case a camelCase), convertir XML a JSON, agregar headers de seguridad o eliminar campos sensibles para ciertos clientes. Los gateways modernos utilizan JSONPath, jq o Liquid Templates.

12. ¿Qué es el versionado de API en el gateway?

El versionado de API en el gateway significa que el gateway gestiona múltiples versiones de API en paralelo. /v1/users se enruta al backend antiguo, /v2/users al nuevo. El gateway puede transformar versiones, permitiendo que una solicitud v1 funcione también en el backend v2. Esto posibilita migraciones sin breaking changes para clientes existentes.

13. ¿Qué es la degradación elegante en el contexto de la composición de API?

Degradación elegante significa que ante un fallo parcial de backend la API sigue funcionando con funcionalidad reducida. El gateway entrega valores de fallback para servicios caídos y los marca en la respuesta. El cliente puede mostrar los datos faltantes (por ejemplo, “Pedidos no disponibles actualmente”) en lugar de mostrar la página completa con errores.

14. ¿Cuál es la diferencia entre API Gateway y Service Mesh?

Un API Gateway gestiona tráfico externo con patrones como BFF, composición y autenticación. Un Service Mesh (Istio, Linkerd) gestiona la comunicación interna entre microservicios con mTLS, reintentos y circuit breaking. En arquitecturas modernas existen ambos: API Gateway afuera para clientes, Service Mesh adentro para comunicación entre servicios.

15. ¿Cuál es el anti-patrón más importante en el API Gateway?

El anti-patrón más importante es usar el gateway como capa de lógica de negocio. Cuando cálculos de dominio, validaciones o lógica de flujos se colocan en el gateway, se vuelve difícil de probar, los equipos dependen unos de otros y el gateway se convierte en un cuello de botella. El gateway debe contener lógica de infraestructura e integración, no lógica de negocio.

Continúa tu camino de aprendizaje en APIs

El siguiente artículo aborda documentación de APIs con Swagger y OpenAPI, donde aprenderás cómo documentar tus APIs de forma clara, legible por máquinas y conforme a estándares.

Fuentes y recursos adicionales

  1. https://microservices.io/patterns/apigateway.html
  2. https://samnewman.io/patterns/
  3. https://docs.konghq.com/hub/
  4. https://learn.microsoft.com/en-us/azure/api-management/
  5. https://martinfowler.com/bliki/StranglerFigApplication.html

Libros recomendados para desarrollo de APIs

Keine Bücher für Kategorie "api-development" gefunden.

Volver al blog
Share:

Entradas relacionadas