Para conectar dos sistemas tienes tres transportes: una API que consultas cuando necesitas el dato, un webhook que te avisa en cuanto algo cambia y una cola de mensajes que guarda el aviso hasta que puedas procesarlo. Lo que los separa es qué ocurre cuando el otro extremo no responde. Lo montamos en las integraciones a medida de Codezone.
Elegir mal se paga en pedidos que entran dos veces porque el proveedor reintentó, avisos perdidos durante un despliegue y alguien cuadrando a mano lo que el sistema tenía que escribir solo.
Al terminar sabrás qué transporte pedir para cada flujo, y dónde encaja la capa intermedia que traduce entre ERP, CRM y software antiguo.
Qué resuelve cada uno
Una API es una pregunta: tu sistema pide el dato y espera respuesta. Un webhook es un aviso: el origen lanza una llamada HTTP a tu endpoint cuando ocurre el evento. Una cola es un buzón: el productor deja el mensaje y el consumidor lo recoge cuando puede.
Dirección, latencia y caídas
La API va de quien necesita el dato hacia quien lo tiene, con acoplamiento temporal: si el destino está caído, tu petición falla ahí mismo. El webhook invierte la dirección y te deja a merced del emisor, que no siempre guarda el aviso. La cola rompe ese acoplamiento: el mensaje sobrevive a la caída del consumidor.
De ahí sale la pregunta útil: si el otro extremo desaparece diez minutos, qué se pierde. Si se reintenta sin consecuencias, basta con API o webhook. Si se pierde un pedido, necesitas cola.
Entrega al Menos una Vez: el Duplicado es el Contrato
Ningún transporte asíncrono serio promete entregar exactamente una vez. Las colas estándar de Amazon SQS garantizan entrega al menos una vez y advierten de que, por su arquitectura distribuida, puede entregarse más de una copia del mismo mensaje, según la referencia de colas estándar de SQS.
Los webhooks van igual: Stripe recomienda registrar los identificadores de evento ya procesados para no repetirlos. El receptor tiene que ser idempotente, con una clave estable por mensaje guardada antes de escribir nada.
Reintentos, cola de fallidos y orden
Un mensaje que falla se reintenta; uno que falla siempre hay que apartarlo. En SQS lo controla la política de redrive con `maxReceiveCount`: las veces que un consumidor puede recibirlo antes de moverlo a la cola de fallidos. RabbitMQ manda a su dead letter exchange los rechazados, los caducados por TTL y los que superan el `delivery-limit`, 20 por defecto en colas quorum desde la versión 4.0, según la documentación de colas quorum de RabbitMQ.
El orden se descubre tarde. SQS estándar hace un intento de mejor esfuerzo y los mensajes pueden llegar desordenados. Kafka garantiza el orden dentro de una partición y manda los eventos con la misma clave a la misma. Si necesitas que "pedido creado" llegue antes de "pedido cancelado", la clave de ordenación va por entidad.
Cuándo la Cola Deja de Ser Opcional
- Volumen irregular: si el pico multiplica varias veces la media, la cola absorbe la punta sin tirar el consumidor.
- Dinero o stock: cuando perder un aviso obliga a cuadrar a mano, el mensaje tiene que sobrevivir al reinicio.
- Proceso lento: si tratar el evento tarda más que el plazo del emisor, responde rápido y procesa después. GitHub pide un 2XX en diez segundos y recomienda encolar la carga.
- Varios consumidores del mismo hecho: facturación, almacén y avisos leen el mismo evento sin que el origen sepa cuántos son.
- Cuándo no hace falta: una consulta de stock que el usuario mira en pantalla se resuelve con API. Una cola ahí solo añade latencia.
La combinación habitual no elige una sola: el origen avisa por webhook, el receptor valida la firma, encola y responde en milisegundos, y un consumidor trabaja contra la API del destino con reintentos. Es el patrón de el portal donde el proveedor consulta su pedido y de la cadena de aprobación de una compra.
CodeZone Pro Tip: guarda la clave de idempotencia antes de tocar el ERP y aparta el mensaje en la cola de fallidos cuando agote los reintentos, para que un reintento del emisor no duplique el pedido ni bloquee la cola.
import crypto from "node:crypto";
const MAX_INTENTOS = 5;
export async function procesarMensaje(msg, db, erp, colaFallidos) {
// Clave derivada del contenido del evento, no del id de entrega:
// el emisor cambia el id al reintentar, el evento sigue siendo el mismo.
const clave = crypto
.createHash("sha256")
.update(`${msg.tipo}|${msg.entidadId}|${msg.version}`)
.digest("hex");
// Insert con conflicto ignorado: la base de datos decide quien gana
// la carrera si dos consumidores cogen copias del mismo mensaje.
const { rowCount } = await db.query(
`INSERT INTO mensajes_procesados (clave) VALUES ($1)
ON CONFLICT (clave) DO NOTHING`,
[clave]
);
if (rowCount === 0) return { estado: "duplicado", clave };
try {
await erp.crearPedido(msg.datos, { idempotencyKey: clave });
return { estado: "ok", clave };
} catch (err) {
// Si falla despues de reservar la clave hay que liberarla,
// o el reintento se descartara como duplicado sin haber escrito nada.
await db.query(`DELETE FROM mensajes_procesados WHERE clave = $1`, [clave]);
if (msg.intentos + 1 >= MAX_INTENTOS) {
await colaFallidos.enviar({ ...msg, motivo: err.message });
return { estado: "descartado", clave };
}
throw err; // devuelve el mensaje a la cola para el siguiente intento
}
}Esas líneas evitan los dos incidentes más caros del primer mes: el pedido duplicado que alguien anula a mano y el mensaje envenenado que se reintenta sin parar y para la cola entera.
Lo que Cuesta Elegir el Transporte Equivocado
Una integración mal transportada no falla el primer día. Falla el día del pico, y ahí el coste deja de ser técnico: un almacén que sirve lo que no hay.
Antes de decidir, escribe por cada flujo quién tiene el dato, cada cuánto cambia y qué pasa si el aviso se pierde. El resto se discute en el enfoque de integración de sistemas empresariales en Madrid y se presupuesta con cuánto cuesta integrar dos programas con una API, tras decidir una API propia frente a una de terceros.
El síntoma de que el transporte no da más de sí es conocido: cuando el ERP y el CRM dejan de hablarse y alguien hace de puente con una hoja de cálculo. Si además hay un agente que escribe en el ERP, la idempotencia pasa de recomendable a obligatoria.
Si tienes dos sistemas que ya se hablan a medias, miramos qué transporte encaja en tu caso.