Sistema
Arquitectura
El pipeline se organiza en 4 dominios con responsabilidades separadas. El diagrama completo — incluyendo tipos de conexión y el camino de request en vivo — es el mismo architecture.svg que vive en la raíz del repo; acá se explica cada banda y la decisión que las amarra.
Las 4 bandas
Entrenamiento offline · Python
Limpieza de datos, ingeniería de features, entrenamiento con XGBoost y export a ONNX. Corre fuera del camino de request en vivo — nada de esto se ejecuta por cada predicción.
Infraestructura core
Postgres (feature_metadata, features, prediction_logs, backend de MLflow), Redis (online store de Feast), MLflow (tracking + registry) y el feature server de Feast.
Serving + monitoreo
La API de inferencia (Node.js/Fastify + ONNX Runtime) sirve predicciones; Prometheus scrapea sus métricas; Evidently compara la distribución de entrenamiento contra el tráfico reciente.
Producto
El dashboard en Next.js — la única pieza con la que habla el navegador. Todo su fetching a las demás capas es server-side.
La decisión clave: todo pasa por el dashboard
El navegador solo le habla al dashboard — nunca directo a la API de inferencia, a MLflow, a Prometheus o a Postgres. Todo ese fetching pasa por el backend de Next.js (Server Components / Route Handlers), usando los nombres de servicio internos de Docker Compose.
Esto resuelve dos problemas con una sola regla: evita tener que configurar CORS en servicios que no lo necesitan por ningún otro motivo, y separa limpiamente "código que corre en el servidor, con nombres internos de red" de "código que corre en el navegador, con puertos mapeados al host" — un gotcha real que ya había mordido al proyecto antes en la integración de Feast/MLflow desde los scripts de entrenamiento. Un único punto de entrada, sin esa ambigüedad.
Por qué Python + Node, y no un solo lenguaje
En vez de forzar todo el pipeline a un solo lenguaje, el trabajo se divide según dónde cada tecnología aporta más:
- Python para entrenamiento, definición/materialización de features en el feature store y reportes de drift — el ecosistema (scikit-learn, XGBoost, el SDK de Feast, Evidently) no tiene equivalente maduro en Node.
- Node.js / TypeScript para la API de inferencia (sirviendo el modelo exportado a ONNX) y el dashboard — las piezas con las que interactúa el usuario final, donde un stack de producción más pulido importa más.
El split es en sí mismo parte del argumento técnico: no es "usé lo que ya sabía", sino una decisión defendible sobre dónde vive cada responsabilidad del sistema.