
Una historia real sobre cómo convertimos el caos de archivos FTP en un sistema robusto de procesamiento de órdenes
El Problema: Cuando lo “Simple” se Vuelve Complejo
Era un lunes cualquiera cuando recibí esa llamada que todo arquitecto de software teme: “La integración con el cliente se está cayendo constantemente y ya perdimos 3 archivos de órdenes este fin de semana”.
La empresa de logística en donde colaboraba tenía un cliente importante que, por razones de seguridad corporativa, no podía consumir APIs modernas. Su solución: subir archivos planos vía FTP cada mañana con las órdenes del día. Simple, ¿verdad?
Incorrecto.
La Arquitectura del Caos
Nuestro sistema original parecía directo en el papel:
Cliente sube archivo → Worker lee FTP → Procesa líneas → Inserta en SAP Business One
Pero la realidad era muy diferente:
- Archivos de hasta 10,000 órdenes que llegaban en horarios impredecibles
- SAP Business One corriendo en servidores remotos con latencias variables
- Conexiones de red inestables que cortaban el procesamiento a medias
- Sin visibilidad de qué órdenes se procesaron exitosamente
- Reintentos manuales que a veces duplicaban datos
El resultado: caos operativo y un cliente cada vez más frustrado.
El Momento de Quiebre
El viernes negro llegó cuando un archivo de 8,500 órdenes se procesó “exitosamente” según nuestros logs, pero SAP solo registró 3,200 entradas. Las 5,300 órdenes restantes se perdieron en el limbo digital.
Mientras investigábamos, descubrimos el horror:
- Nuestro worker se había caído 7 veces durante la madrugada
- Los reintentos automáticos generaron órdenes duplicadas
- SAP había rechazado silenciosamente 2,100 órdenes por direcciones inválidas
- No teníamos forma de saber exactamente dónde falló cada línea
- Nuestra integración dependía de una integración en SAP con unos bots arcaicos para enviar los datos a otra integración de logística y no era capaz de gestionar los datos duplicados
Necesitábamos una solución robusta. Ya.
Enter Temporal.io: La Luz al Final del Túnel

Después de evaluar varias opciones, decidimos apostar por Temporal.io. La promesa era tentadora: workflows duraderos que sobreviven a fallos, reintentos inteligentes, y visibilidad completa del proceso.
Rediseñando la Arquitectura
Transformamos nuestro sistema monolítico en workflows resilientes:
📁 Monitor FTP (cada minuto)
├─ 🔄 Workflow: Procesar Archivo
│ ├─ 📋 Actividad: Mover a Processing
│ ├─ 📖 Actividad: Leer Líneas
│ └─ 🔄 Para cada línea:
│ ├─ 🔄 Sub-workflow: Procesar Línea
│ ├─ 🏠 Actividad: Validar/Crear Dirección (3 reintentos)
│ ├─ 💾 Actividad: Insertar en SAP (5 reintentos)
│ └─ ✅ Marcar como completada
├─ 📊 Generar Reporte
└─ 📧 Notificar Resultados
La Magia de los Reintentos Inteligentes
El diseño más brillante fue la estrategia de reintentos por capas:
Para direcciones:
retry: {
initialInterval: '1s',
maximumAttempts: 3,
backoffCoefficient: 1.5,
nonRetryableErrorTypes: ['ValidationError']
}
Para SAP Business One:
retry: {
initialInterval: '5s', // SAP es lento
maximumAttempts: 5, // Más persistencia
maximumInterval: '2m', // Tiempo máximo entre intentos
backoffCoefficient: 2.0 // Backoff exponencial
}
Los Desafíos de SAP Business One
SAP resultó ser el verdadero villano de nuestra historia. Descubrimos que:
- Las conexiones expiran cada 30 minutos sin previo aviso
- La API de SAP puede tardar hasta 45 segundos en responder a una inserción
- Los errores de SAP son crípticos (“Error general en la operación”)
- No tenemos control sobre la instalación – está en servidores del cliente
Temporal nos salvó aquí también. Cada fallo de SAP se registraba con el stack trace completo, y los reintentos inteligentes distinguían entre errores temporales (reintentar) y errores permanentes (marcar línea como fallida).
El Resultado: De Caos a Confianza
Antes vs Después
| Métrica | Métrica | Después |
| Visibilidad | “¿Se procesó?” | Dashboard en tiempo real |
| Recuperación | Manual, propenso a errores | Automática |
| Tasa de éxito | ~85% (con duplicados) | 99.2% |
| Tiempo de diagnóstico | Horas investigando logs | Minutos en el dashboard |
| Confianza del cliente | Baja | Alta |
Dashboard que Cambió Todo
La interfaz web de Temporal nos dio superpoderes:
🔄 Procesando: pedidos_20240322_08:30.txt
├─ ✅ 8,247 órdenes completadas
├─ 🔄 Procesando línea 8,248…
├─ ⚠️ 12 direcciones requirieron creación
├─ 🔄 23 reintentos en SAP (conexión lenta)
└─ ⏱️ Tiempo estimado: 8 minutos
Los gerentes podían ver el progreso en vivo. Ya no más llamadas a las 6 AM preguntando si “llegaron las órdenes de hoy”.

Lecciones Aprendidas
1. La Importancia de la Granularidad
Procesar línea por línea en workflows separados fue clave. Si una orden falla, no afecta las demás 9,999.
2. SAP Business One Requiere Paciencia
Aprendimos a vivir con las limitaciones de SAP:
- Timeouts generosos (hasta 2 minutos por inserción)
- Reintentos agresivos pero inteligentes
- Logs detallados para debugging
3. La Visibilidad es Poder
El dashboard de Temporal transformó cómo operamos. De reaccionar a problemas a anticiparlos.
4. Los Reintentos No Son Todos Iguales
Diferentes actividades necesitan diferentes estrategias:
- Validaciones: Fallo rápido, pocos reintentos
- Conexiones de red: Muchos reintentos con backoff
- SAP: Paciencia extrema
El Impacto Final
6 meses después:
✅ El cliente nos renovó el contrato por 3 años más
✅ Procesamos exitosamente 2.3 millones de órdenes
✅ Reducimos el tiempo de investigación de problemas en 95%
✅ Eliminamos 100% de los archivos perdidos
Reflexiones Técnicas
¿Valió la pena la complejidad adicional de Temporal? Absolutamente.
La curva de aprendizaje fue pronunciada, pero los beneficios superaron ampliamente los costos:
- Desarrollo: 40% más tiempo inicial
- Mantenimiento: 80% menos tiempo
- Confiabilidad: De pesadilla a ejemplo
La Pesadilla de la Inestabilidad: Cuando SAP Business One Se Vuelve Impredecible
Tres semanas después del despliegue, cuando empezábamos a celebrar victoria, SAP Business One nos recordó por qué es tan temido en el mundo de las integraciones.
El Caos Aleatorio
Los reportes matutinos se volvieron una ruleta rusa:
Lunes: 8,500 órdenes → 127 fallidas (aleatorias)
Martes: 6,200 órdenes → 891 fallidas (aleatorias)
Miércoles: 4,100 órdenes → 45 fallidas (aleatorias)
Jueves: 9,800 órdenes → 2,341 fallidas (aleatorias)
No había patrón. Las órdenes fallaban de forma completamente aleatoria, y los mensajes de error de SAP eran inútiles:
- “Error general en la operación”
- “Timeout de conexión”
- “El servidor no responde”
- “Error interno del sistema”
La Realidad Brutal de SAP Business One
Después de weeks de frustración, la verdad emergió. SAP Business One, especialmente en instalaciones legacy que no controlamos, sufre de:
1. Tiempos de respuesta erráticos:
Inserción 1: 200ms ✅
Inserción 2: 45 segundos ❌ (timeout)
Inserción 3: 1.2 segundos ✅
Inserción 4: 2 minutos ❌ (timeout)
2. Inestabilidad de conexiones:
- La API se desconecta sin previo aviso
- Reconexiones automáticas fallan silenciosamente
- El servidor “se cuelga” durante picos de carga
3. Comportamiento no determinista:
- La misma operación puede fallar 3 veces y exitosa en la 4ta
- Error messages que no corresponden al problema real
- Estados internos inconsistentes
La clave estaba en entender que SAP Business One no es un API moderno. Es un sistema ERP de los años 2000 que maneja concurrencia y carga de forma impredecible.
La Estrategia de Reintentos Inteligentes
Aquí es donde Temporal.io demostró su verdadero valor. Implementé una estrategia de reintentos adaptativos:
// Reintentos específicos para SAP Business One
const sapActivities = proxyActivities<Activities>({
startToCloseTimeout: '5m', // SAP puede tardar muchísimo
retry: {
initialInterval: '5s', // Empezar con espera moderada
backoffCoefficient: 1.5, // Incremento gradual, no agresivo
maximumInterval: '2m', // Hasta 2 minutos entre intentos
maximumAttempts: 8, // Más persistencia
nonRetryableErrorTypes: [
'ValidationError', // Datos inválidos
'DuplicateKeyError' // Ya existe
]
}
});
// Para operaciones críticas (direcciones), aún más agresivo
const criticalSapActivities = proxyActivities<Activities>({
startToCloseTimeout: '8m',
retry: {
initialInterval: '10s',
backoffCoefficient: 2.0,
maximumInterval: '5m', // Hasta 5 minutos!
maximumAttempts: 12, // Máxima persistencia
}
});
El Breakthrough: Jitter y Throttling Dinámico
Pero el verdadero breakthrough vino cuando implementé dos técnicas que había aprendido en sistemas distribuidos de alta escala:
1. Jitter Exponential Backoff:
// Agregar aleatoriedad para evitar "thundering herd"
const jitter = Math.random() * 0.3; // 30% de variación
const finalDelay = baseDelay * (1 + jitter);
2. Throttling Dinámico Basado en Éxito:
class SAPThrottleManager {
private successRate = 1.0;
private recentOperations: boolean[] = [];
calculateOptimalDelay(): number {
// Si SAP está fallando mucho, ir más lento
if (this.successRate < 0.7) {
return 30000; // 30 segundos entre operaciones
} else if (this.successRate < 0.9) {
return 10000; // 10 segundos
} else {
return 2000; // 2 segundos (velocidad normal)
}
}
recordResult(success: boolean) {
this.recentOperations.push(success);
if (this.recentOperations.length > 100) {
this.recentOperations.shift();
}
this.successRate = this.recentOperations
.filter(Boolean).length / this.recentOperations.length;
}
}
El Momento de la Revelación
El sistema comenzó a adaptarse automáticamente al estado de SAP:
SAP funcionando bien:
⚡ Procesando a velocidad normal (2s entre operaciones)
✅ Tasa de éxito: 98%
SAP con problemas:
🐌 SAP inestable detectado, reduciendo velocidad...
⏱️ Esperando 30s entre operaciones
🔄 Reintentando hasta 12 veces por operación
✅ Tasa de éxito mantenida: 94%
El Resultado Transformador
Antes (sistema rígido):
- Fallos aleatorios sin recuperación
- Pérdida de órdenes en cada episodio inestable de SAP
- Tiempo de recuperación: manual, horas
Después (sistema adaptativo):
- 0 órdenes perdidas en 6 meses
- Adaptación automática a la inestabilidad de SAP
- Tiempo de recuperación: automático, minutos
La Lección Más Profunda
Esta experiencia me enseñó que el verdadero arte de las integraciones no está en hacer que los sistemas funcionen perfectamente, sino en hacer que funcionen a pesar de su imperfección.
SAP Business One nunca dejará de ser inestable en esa instalación legacy. Pero nuestro sistema aprendió a danzar con el caos, adaptándose dinámicamente a cada cambio de humor de SAP.
La flexibilidad de Temporal no solo nos salvó de los fallos – nos permitió crear un sistema que se vuelve más inteligente con cada error.
Conclusión: Cuando las Herramientas Correctas Marcan la Diferencia
Esta experiencia me enseñó que no todos los problemas de integración son iguales. Cuando tienes:
- ❌ Sistemas externos fuera de tu control (SAP, FTP)
- ❌ Procesos críticos que no pueden fallar
- ❌ Necesidad de visibilidad y trazabilidad completa
…entonces herramientas como Temporal.io no son lujo, son necesidad.
Pero más importante aún: las herramientas modernas potencian el conocimiento acumulado. Sin Temporal, identificar los errores y recrear un worker con reintentos me hubiese supuesto un esfuerzo adicional y sin tener todas las ventajas. Sin mi experiencia previa con ERP, nunca habría conectado los puntos tan rápido.
Hoy, nuestro sistema procesa silenciosa y confiablemente miles de órdenes. El caos se convirtió en predictibilidad, y las noches de insomnio debuggeando se transformaron en dashboards verdes y reportes automáticos.
A veces la mejor arquitectura no es la más simple, sino la más resiliente. Y la mejor solución combina tecnología moderna con sabiduría ganada a través de la experiencia.
¿Has vivido el caos de integraciones con sistemas legacy? ¿Cómo resolviste los desafíos de visibilidad y confiabilidad? Cuéntame tu historia en los comentarios.
Tags: #temporal #integration #sap #workflow #resilience #logistica
