Integrar dos sistemas sin perder datos en el camino
Reintentos, idempotencia y trazabilidad: las tres cosas que separan una integración que funciona de una que parece funcionar.
Casi todas las integraciones rotas que me tocó arreglar empezaron igual: alguien escribió un script que lee de un lado y escribe del otro. Anduvo. Lo dejaron andando. Seis meses después hay facturas que no están y nadie sabe desde cuándo.
El script no estaba mal escrito. Le faltaban tres cosas que nadie pide en la reunión inicial porque no se ven hasta que fallan.
1. La red falla, y falla en el peor momento
Cuando tu código le pega a una API, hay tres finales posibles: anduvo, falló, o no sabés. El tercero es el interesante.
Si la conexión se corta después de que el pedido salió pero antes de que llegue la respuesta, tu lado registra un error y el otro lado registra un alta. Reintentás, y ahora hay dos facturas.
La respuesta no es “reintentar menos”. Es reintentar con cabeza:
- Backoff exponencial con jitter. Si reintentás cada un segundo, cuando el otro sistema se cae todos tus procesos lo martillan juntos y le impedís levantarse. Esperá 1 s, 2 s, 4 s, 8 s, y sumale un azar de hasta un segundo para que no se sincronicen.
- Un techo. Después de N intentos, el mensaje va a una cola aparte y alguien lo mira. Reintentar para siempre es esconder el problema.
- Distinguí qué se reintenta. Un 503 se reintenta. Un 400 no: el pedido está mal y lo va a estar siempre. Reintentar un 400 es gastar recursos para fallar más tarde.
2. Idempotencia: poder repetir sin romper
Si el punto anterior te deja reintentando, necesitás que repetir sea inofensivo. Eso se llama idempotencia y es la pieza que más se saltea.
La forma práctica: cada operación lleva una clave propia, estable, derivada del dato y no del momento. El número de la factura sirve. Un UUID generado antes de mandar, también. Date.now() no, porque cambia en cada intento.
El receptor guarda esas claves y, si ve una repetida, devuelve el resultado anterior en lugar de crear algo nuevo. Si el receptor es un sistema ajeno que no hace nada de esto, lo hacés vos: antes de dar de alta, preguntás si ya existe. Es una llamada más y te evita el duplicado.
Una integración idempotente se puede volver a correr entera después de un desastre. Una que no lo es, no se puede tocar sin miedo, y el miedo es lo que hace que nadie la arregle.
3. Trazabilidad: poder contestar “¿qué pasó con el pedido 4412?”
Esta es la que te va a salvar la relación con el cliente.
Cada mensaje que cruza lleva un identificador de correlación que se arrastra de punta a punta y aparece en todos los registros. Cuando alguien pregunta por un pedido, buscás ese identificador y ves la historia completa: cuándo entró, cuántos intentos hubo, qué devolvió el otro lado, cuándo se dio por bueno.
Sin eso, la respuesta honesta a “¿qué pasó con el 4412?” es “no sé”, y esa respuesta cuesta más que todo el desarrollo.
Dos detalles que importan: guardá el cuerpo del pedido y de la respuesta, al menos un tiempo, porque “devolvió error” no sirve para nada sin el mensaje; y no guardes datos personales que no necesitás, porque el registro también es un lugar donde se filtran cosas.
Lo mínimo para dormir tranquilo
Si estás por conectar dos sistemas y tenés poco tiempo, el orden es este:
- Clave idempotente en cada operación.
- Reintentos con backoff y una cola de fallidos.
- Identificador de correlación en todos los registros.
- Una alerta cuando la cola de fallidos deja de estar vacía.
Son cuatro cosas, se hacen en días, no en meses, y son la diferencia entre una integración que te deja dormir y una que te obliga a revisar planillas los lunes.
Lo demás —paneles, métricas, reprocesos automáticos— viene después y se construye solo si estas cuatro están.