Seis patrones de integración para conectar servicios de Node.js de manera fiable
Aprenda los patrones fundamentales detrás de integraciones sólidas con Node.js: solicitud-respuesta, polling, webhooks, clave API, autenticación JWT y OAuth, reintentos con retroceso temporal, y mapeo de datos.
Fuentes: 6 API Integration Patterns Every Node.js Integration Engineer Must Know
Enviar una solicitud HTTP es sencillo; mantener una integración funcionando cuando el otro sistema es lento, está inactivo o tiene una estructura diferente es la verdadera tarea. Esta guía aborda seis patrones que se repiten cuando los servicios de Node.js se comunican con proveedores de pagos, CRM, ERP y entre sí, además de los problemas que separan una demostración de una integración fiable.
1. Solicitud-respuesta: la base síncrona
En el modelo de solicitud-respuesta, un cliente envía una solicitud, el servidor realiza el trabajo y la respuesta llega a través de la misma conexión. Este modelo cubre la mayoría de las operaciones cotidianas: iniciar sesión, crear o actualizar registros, obtener información de un cliente, eliminar un recurso.
app.get("/users/:id", async (req, res) => {
const user = await db.findUser(req.params.id);
res.json(user);
});
Es sencillo de depurar y constituye la opción predeterminada para operaciones CRUD. Su debilidad radica en las tareas que tardan mucho en ejecutarse: un informe extenso o un archivo grande pueden superar los tiempos de espera del cliente o del proxy. Cabe señalar también que este controlador devuelve null con el estado 200 cuando el usuario no existe; un verdadero endpoint debería responder con 404.
2. Polling: solicitar hasta que la tarea se complete
Cuando no es posible generar un resultado de inmediato, el servidor puede aceptar la tarea, devolver un identificador y permitir que el cliente verifique nuevamente. Los casos típicos incluyen esperar a que se procese un pago, se genere un informe, se transcode un video o se envíe un pedido.
Al iniciar una tarea se devuelve su ID:
POST /reports
Response:
{
"jobId": "abc123"
}
Luego, el cliente verifica periódicamente el endpoint de estado:
GET /reports/abc123/status
hasta que la tarea indique que ha finalizado:
{
"status": "completed"
}
El polling es sencillo y compatible con los firewalls, por lo que muchos sistemas empresariales siguen dependiendo de él. El costo radica en el tráfico desperdiciado, ya que la mayoría de las verificaciones devuelven “todavía no”. Espacie las solicitudes (respetando Retry-After si se envía), establezca un plazo general y maneje tanto los casos fallidos como los completados.
3. Webhooks: permitir que la otra parte lo llame
Los webhooks invierten la dirección. En lugar de que su servicio haga consultas repetidamente, el proveedor envía una solicitud HTTP a su endpoint cuando ocurre algo: un pago tiene éxito, se realiza un pedido, llega un mensaje, un cliente se registra o cambia el inventario. Stripe, Slack, GitHub y Shopify dependen en gran medida de este modelo.
Un receptor mínimo en Express:
app.post("/webhook/payment", (req, res) => {
const event = req.body;
if (event.type === "payment.success") {
console.log("Payment received!");
}
res.sendStatus(200);
});
Esto muestra la estructura básica, pero un receptor para producción necesita más elementos:
- Verifique al remitente. Cualquiera puede publicar en una URL pública. Los proveedores suelen firmar cada carga de trabajo, y usted debe verificar esa firma (generalmente en comparación con el cuerpo de la solicitud sin procesar) antes de confiar en el evento.
- Esté preparado para duplicados. Las entregas generalmente se intentan nuevamente hasta que se confirme su recepción, por lo que el mismo evento puede llegar más de una vez. Almacene los IDs de los eventos procesados y haga que los manejadores sean idempotentes.
- Confirme rápidamente. Devuelva un código 2xx de inmediato y aplique el trabajo lento a una cola; de lo contrario, el proveedor podría agotar su tiempo de espera y reenviarlo.
La integración basada en eventos es cada vez más preferida porque elimina el tráfico de consulta continua.
4. Autenticación: demostrar quién está realizando la llamada
Toda integración comienza con credenciales. Tres enfoques cubren la mayoría de los casos.
Claves API
El esquema más simple envía un secreto compartido en un encabezado:
GET /users
x-api-key: abc123xyz
En Node.js con axios, la clave debe provenir de la configuración, nunca del código fuente:
axios.get(url, {
headers: {
"x-api-key": process.env.API_KEY
}
});
Las claves de API son adecuadas para herramientas internas e integraciones simples entre servidores. Por sí solas no tienen fecha de vencimiento ni identifican al usuario, por lo que se deben rotar y delimitar en el ámbito más restringido que permita el proveedor.
Tokens Web JSON
Los JWT permiten la autenticación sin estado. La secuencia habitual es:
- El usuario inicia sesión.
- El servidor emite un token firmado.
- El cliente guarda el token.
- Cada solicitud posterior lo incluye en un encabezado:
Authorization: Bearer eyJhbGciOiJIUzI1NiIs...
Emisión de uno en Node.js:
const token = jwt.sign(
{ userId: 1 },
process.env.JWT_SECRET
);
Cualquier servicio que cuente con la clave de verificación puede validar el token sin necesidad de un almacén de sesiones, lo cual es adecuado para los microservicios. El problema radica en la revocación: un token permanece válido hasta que expira, por lo que siempre se debe establecer el parámetro expiresIn, algo que este fragmento omite.
OAuth 2.0
OAuth 2.0 es lo que permite el acceso delegado: “Iniciar sesión con Google”, inicio de sesión en Facebook, Microsoft Enterprise Single Sign-On, conectores CRM y cualquier aplicación de terceros que actúe en nombre del usuario. En el flujo común de código de autorización:
- El usuario aprueba el acceso solicitado en el proveedor.
- El proveedor redirige al usuario con un código de autorización de corta duración.
- Su servidor intercambia ese código por un token de acceso.
- Las llamadas a la API se realizan con el token de acceso.
Vale la pena aprender en profundidad: tokens de acceso y de actualización, el flujo de código de autorización, el flujo de credenciales del cliente para llamadas máquina a máquina, PKCE y OpenID Connect, una capa de identidad sobre OAuth.
5. Resiliencia: diseño para fallos
Las redes se caen y las dependencias dejan de funcionar. Las integraciones fiables asumen que esto ocurrirá.
Volver a intentar llamadas fallidas
Un bucle básico de reintentos:
for (let i = 0; i < 3; i++) {
try {
return await axios.get(url);
} catch (error) {
console.log("Retrying...");
}
}
Tal como está escrito, vuelve a intentarlo de inmediato sin pausa, y si los tres intentos fallan devuelve undefined en lugar de lanzar el último error, por lo que quien llama no puede saber qué salió mal. Vuelva a lanzar el error después del intento final, y solo intente de nuevo los fallos transitorios (errores de red, tiempos de espera, códigos 5xx, 429), no los códigos 4xx que fallarán de la misma manera en cada ocasión. Tenga cuidado al volver a intentar solicitudes no idempotentes como los pagos, a menos que la API soporte claves de idempotencia.
Tiempo de espera
Una solicitud sin tiempo de espera puede quedar atascada indefinidamente y ocupar recursos mientras lo está. Siempre establezca uno:
axios.get(url, {
timeout: 5000
});
Retraso exponencial
Volver a intentarlo a intervalos fijos sigue sobrecargando un servicio con problemas:
1s
1s
1s
1s
Doblar el tiempo de espera cada vez le da espacio para recuperarse:
1s
2s
4s
8s
16s
El cálculo se realiza en una sola línea:
const delay = attempt =>
Math.pow(2, attempt) * 1000;
Establezca un límite máximo para el retraso y añada variaciones aleatorias para que los muchos clientes que fallan al mismo tiempo no intenten nuevamente de forma sincronizada.
Disyuntores eléctricos
Un disyuntor eléctrico cuenta las fallas en un servicio downstream y, al superar un umbral, deja de llamarlo durante un período de enfriamiento antes de enviar una solicitud de prueba. Esto evita fallos en cadena, agotamiento de recursos y interrupciones en todo el sistema. Opossum es una opción común en Node.js; Resilience4j cumple esta función en Java, y Hystrix se utiliza en sistemas más antiguos.
6. Transformación de datos: traducción entre sistemas
Rara vez dos sistemas coinciden en la estructura de los datos, por lo que una gran parte del trabajo de integración consiste en la traducción.
Mapeo de campos
Un sistema utiliza camelCase:
{
"firstName": "John"
}
otro espera snake_case:
{
"first_name": "John"
}
Un pequeño mapeador conecta ambos:
function transform(user) {
return {
first_name: user.firstName
};
}
Las funciones de mapeo puras son fáciles de probar unitariamente y evitan que las peculiaridades de los proveedores afecten la lógica del negocio.
JSON y XML
Muchos sistemas heredados todavía utilizan XML, mientras que los servicios más recientes generan JSON; por eso una capa de integración suele convertir entre ambos en ambas direcciones.
Fechas
Un lado puede enviar el formato ISO:
2026-06-26
mientras que el otro espera la notación con el día primero:
26/06/2026
Realice conversiones explícitas y sea claro respecto a las zonas horarias cuando los valores incluyan horas; una fecha desplazada más allá de la medianoche es un error clásico en la integración.
Cantidades monetarias
Un servicio indica una cantidad decimal:
{
"amount": 10.50
}
El otro requiere unidades fraccionarias enteras:
{
"amount_cents": 1050
}
Los valores de punto flotante no pueden representar con exactitud cada decimal, por lo que es necesario redondear al convertir (por ejemplo Math.round(amount * 100)) y preferir centavos enteros en el interior del sistema.
Cómo se combinan los patrones en la práctica
Un diseño empresarial típico coloca una pasarela de Node.js delante de varios servidores backend:
Frontend
|
Node.js API Gateway
|
+-- Authentication Service
+-- Payment Service
+-- CRM Service
+-- ERP Systems
+-- Notification Service
Estas conexiones combinan los patrones anteriores: APIs de solicitud-respuesta, JWT y OAuth, webhooks, mecanismos de reintentos y protección contra fallos, capas de transformación, además de monitoreo y registro. Para los ingenieros que se dedican al trabajo de integración, las áreas que brindan mayores beneficios primero son las APIs REST, los webhooks, JWT, OAuth 2.0, la transformación de datos y el diseño basado en eventos, seguidas por las técnicas de reintentos y resiliencia, y finalmente los mecanismos de sondeo y protección contra fallos.
Puntos clave
- Utilice el modelo solicitud-respuesta para operaciones rápidas; cambie a polling o webhooks cuando el proceso requiera más tiempo.
- Verifique las firmas de los webhooks, elimine duplicados en los eventos y responda rápidamente.
- Mantenga las credenciales en la configuración, establezca una fecha de vencimiento para los tokens y aprenda adecuadamente los flujos OAuth.
- Intente nuevamente solo ante fallos transitorios, con tiempos de espera definidos, un retroceso exponencial limitado y variabilidad en los intentos.
- Aíslé el mapeo de datos en funciones puras probadas, y trate las fechas y el dinero con especial cuidado.
Lecturas relacionadas
- Anti-Patterns de backend: 7 errores costosos y sus soluciones prácticas — Aprenda cómo detectar y corregir siete errores comunes en la ingeniería de backend, desde controladores sobrecargados hasta errores no manejados, antes de que causen problemas en producción.