Arquitecturas de datos: cómo diseñar tolerancia a fallos cuando el pipeline depende de APIs externas
Arquitecturas de datos: cómo diseñar tolerancia a fallos cuando el pipeline depende de APIs externas
Hay una trampa silenciosa en la mayoría de los pipelines que consumen APIs externas: la arquitectura asume disponibilidad perfecta. El código hace la llamada, espera la respuesta y procesa. En local, funciona. En producción, a las 2 de la madrugada de un martes, falla de formas que nadie había modelado.
No es un problema de la API. Es un problema de diseño. El pipeline no fue construido para degradarse con elegancia; fue construido para funcionar cuando todo va bien. Y eso no es una arquitectura tolerante a fallos: es una arquitectura optimista.
Cuando el origen de datos es externo, el contrato implícito cambia. El SLA del proveedor no es el SLA de tu sistema. Son dos superficies de fallo distintas, y confundirlas genera dependencias frágiles que solo se vuelven visibles en el peor momento.
El error de modelar la API externa como fuente fiable
El primer error de diseño es tratar la API externa como si fuera una base de datos interna: siempre disponible, con latencia predecible, sin sorpresas en el esquema de respuesta.
Las APIs externas de datos tienen comportamientos que no aparecen en la documentación:
- Latencia variable que se dispara bajo carga compartida (multitenant).
- Cambios de esquema no versionados que no rompen el contrato formal pero sí rompen el parser.
- Throttling asimétrico: el rate limit anunciado no siempre coincide con el comportamiento real bajo carga sostenida.
- Respuestas parciales que el servidor devuelve como
200 OKpero con campos vacíos o nulos donde el contrato prometía datos.
Un pipeline ingenuo trata cualquiera de estos casos como una excepción no esperada. Un pipeline resiliente los trata como estados normales del sistema.
Circuit breaker: el patrón que más se menciona y menos se implementa bien
El circuit breaker es el primer recurso que aparece en cualquier artículo sobre resiliencia. La implementación habitual es un contador de errores con un umbral: si superas N fallos en T segundos, el circuito se abre y dejas de intentar llamadas durante un periodo de enfriamiento.
El problema es que muchos equipos implementan el circuit breaker en el nivel equivocado: lo aplican a la llamada HTTP, pero no al flujo de datos downstream. El circuito se abre, las llamadas se detienen, pero el consumidor del pipeline sigue esperando datos que ya no llegan. El fallo silencioso se traslada un nivel más abajo.
Un circuit breaker bien diseñado tiene tres responsabilidades:
- Detectar el estado de degradación de la fuente (no solo errores HTTP, también respuestas vacías o malformadas).
- Notificar al downstream que el flujo está en modo degradado, no simplemente detenerlo sin señal.
- Registrar el estado de apertura con contexto suficiente para el análisis post-mortem: timestamp, causa, volumen afectado, duración.
Sin el punto 2, el downstream interpreta el silencio como normalidad. Sin el punto 3, el equipo no puede mejorar el sistema después del incidente.
Dead letter queues: dónde van los datos que el pipeline no pudo procesar
Cuando una llamada falla o devuelve un resultado inesperado, hay dos opciones: descartar el evento o encolarlo para reintento. Descartar es la opción por defecto en muchos pipelines, y es la más cara a largo plazo.
La dead letter queue (DLQ) es el mecanismo que permite separar el flujo principal del flujo de errores sin bloquear ninguno de los dos. Los eventos que no pueden procesarse en el momento se mueven a la DLQ con metadatos de contexto: causa del fallo, número de reintentos, timestamp original, estado de la respuesta recibida.
Esto tiene implicaciones directas en la arquitectura:
- El consumidor principal no se bloquea esperando que un evento problemático se resuelva.
- Los eventos en la DLQ pueden reprocesarse de forma asíncrona cuando la fuente vuelve a estar disponible.
- La DLQ actúa como indicador de salud del sistema: un volumen creciente de mensajes es una señal temprana de degradación.
En pipelines que procesan señales del universo público de Internet —menciones, tendencias, datos derivados de fuentes heterogéneas—, la DLQ también permite auditar qué segmentos de tiempo quedaron sin cobertura. Es información operativa, no solo un mecanismo de recuperación.
Backpressure: cuando el problema no es el fallo sino el volumen
Hay una categoría de fallos que no parece un fallo: el pipeline recibe más datos de los que puede procesar. El consumidor va acumulando trabajo pendiente, la latencia end-to-end sube, y eventualmente el sistema colapsa bajo su propio peso.
Backpressure es el mecanismo por el que el consumidor señala al productor que reduzca la tasa de emisión. En arquitecturas event-driven bien diseñadas, este mecanismo es explícito. En arquitecturas que no lo modelan, el backpressure ocurre de todas formas, pero de forma destructiva: timeouts, desbordamiento de buffers, pérdida de eventos.
Implementar backpressure en un pipeline que consume APIs externas requiere:
- Medir la cola de procesamiento, no solo la tasa de llamadas.
- Adaptar la frecuencia de polling o el tamaño del batch según el estado del consumidor.
- Priorizar subconjuntos de datos cuando la capacidad es limitada. No todos los datos tienen el mismo valor operativo en el mismo momento.
Este último punto es especialmente relevante cuando el pipeline alimenta análisis en tiempo real: ante capacidad reducida, procesar primero las señales de mayor relevancia contextual es mejor que procesar todo con retraso uniforme.
Observabilidad como parte del diseño, no como añadido posterior
La tolerancia a fallos sin observabilidad es una caja negra. El sistema puede estar degradado durante horas antes de que alguien lo detecte, y cuando lo hace, no hay datos suficientes para entender qué ocurrió.
La observabilidad del pipeline debe cubrir cuatro dimensiones:
- Métricas de flujo: tasa de eventos procesados, tamaño de la cola, latencia end-to-end.
- Métricas de la fuente: tasa de errores por endpoint, distribución de latencia, porcentaje de respuestas vacías o malformadas.
- Estado del circuit breaker: aperturas, cierres, duración en cada estado.
- Volumen en DLQ: por causa de fallo y por ventana temporal.
Herramientas como Prometheus con Grafana, o cualquier stack de observabilidad equivalente, permiten construir dashboards operativos que convierten estos cuatro vectores en alertas accionables. La clave no es la herramienta: es haber definido qué condiciones son anómalas antes de que ocurran.
Plataformas como FeedScale exponen métricas de uso por endpoint que pueden integrarse directamente en estos dashboards, permitiendo cruzar el estado interno del pipeline con el comportamiento real de la fuente.
Antes de escalar, valida que el sistema puede fallar bien
Escalar un pipeline frágil solo amplifica los problemas. Antes de aumentar el volumen de llamadas, el número de fuentes o la frecuencia de procesamiento, la pregunta correcta es: ¿qué ocurre cuando la fuente falla durante 10 minutos? ¿Y durante 2 horas?
Si la respuesta requiere revisar el código para averiguarlo, la arquitectura todavía no está lista para escalar. Un sistema tolerante a fallos tiene respuestas operativas conocidas para cada modo de degradación: qué datos se pierden, cuáles se recuperan, cuánto tarda en volver a la normalidad y quién recibe la señal cuando algo sale mal.
Construir esa certeza antes de escalar no es trabajo extra. Es el trabajo que evita rehacerlo todo cuando el incidente ya ha ocurrido.