Ingeniería de Sistemas en Tiempo Real · Hot Path Audit · Optimización p95/p99 · CULTIVA IA
| Segmento | p50 | p95 | p99 | Estado |
|---|---|---|---|---|
| Provider API ws | 48 | 120 | 310 | OK |
| Ingest Worker → Redis | 12 | 45 | 390 | CRÍTICO |
| Redis → API Gateway | 3 | 8 | 22 | OK |
| API Gateway → SSE | 35 | 180 | 620 | ALERTA |
| ML Model Inference | 90 | 340 | 1.150 | CRÍTICO |
| Browser Render (React) | 55 | 290 | 820 | CRÍTICO |
| End-to-End | 243 | 983 | 3.312 | SLA ROTO |
El cold-start de 1.2 s del pod K8s GPU es el mayor offender. Mantener 2 réplicas siempre calientes con HPA mínimo = 2. Añadir readiness probe con warmup request en el arranque. Para señales asíncronas, precalcular cada 200 ms y cachear en Redis con TTL 500 ms.
HPA minReplicas: 2 · Redis HSET signal:{symbol} · TTL 500ms
El browser NO debe esperar inference en tiempo real. Servir desde caché Redis con X-Signal-Age header.
Inference corre en background asíncrono; si la caché tiene < 500 ms de edad, se sirve directamente.
Añadir canary de stale-hit-rate: alertar si > 5 % de hits tienen age > 1 s.
GET signal:{symbol} → age_ms check → serve or background-refresh
El p99 de 820 ms en browser indica re-renders completos al actualizar un solo símbolo.
Usar react-window para la lista de 500+ instrumentos y React.memo en componentes de señal.
Reducir actualizaciones SSE a delta-patch (JSON Patch RFC 6902) en lugar de payload completo.
FixedSizeList · React.memo · JSON Patch delta · requestAnimationFrame throttle
En hora pico, la cola Redis se llena y los workers caen al 30 %. Añadir backpressure explícita:
si queue.waiting > 500, rechazar mensajes del provider con 429 y reconnectar en 100 ms.
Aumentar concurrencia de workers de 4 a 12. Separar cola de high-priority (orderbook) de low-priority (histórico).
Bull concurrency: 12 · queue.isPaused check · priority queues HOT/COLD
La mayoría de usuarios están en Europa. Fijar Fly.io routing a mad como región primaria
y usar anycast para fallback a ams/lhr solo si > 200 ms RTT. Con SSE ya en la misma región
que Redis, el p99 de gateway debería bajar de 620 ms a ~120 ms.
fly.toml primary_region = "mad" · metrics: fly_edge_http_response_time_seconds
Añadir header X-Orderbook-Age-Ms en cada SSE event. Browser alertar si age > 300 ms (banner "datos retrasados").
En servidor, detector de provider stale: si no hay tick en 2 s → reconectar + incrementar freshness_miss_total en Prometheus.
SSE event: {data, ts_provider, ts_gateway} · Prometheus gauge orderbook_age_ms
Las señales ML no cambian cada 50 ms — agregar en lotes de 200 ms máximo y enviar un único SSE event con batch. Reservar streaming tick-by-tick solo para bid/ask del orderbook. Reduce payload SSE en ~70 % y mejora el render budget del browser.
SSE stream type: TICK | SIGNAL_BATCH · batch_interval_ms: 200
X-Signal-Age. El browser debe mostrar el indicador de frescura siempre.