Proyecto corporativo · Presentado sin referencias a la empresa: solo arquitectura y decisiones.
Motor en Tiempo Real de Apuestas en Vivo
Workers multi-tenant de calificación, límites y liquidación en vivo
Estado
En producción
Rol
Ingeniero backend senior: arquitectura, workers de calificación y contabilidad, resiliencia en Kafka, procedimientos SQL de calificación, workers de reportes, UI administrativa en Blazor y CI/CD.
Arquitectura
Pipeline de calificación con cola en base de datos
Liquidación serializable
50 apuestas por mensaje de Kafka
Reintentos escalonados y dead-letter
Escrituras idempotentes en el libro
Un juego finalizado se califica, las apuestas se liquidan, se agrupan por tenant y se aplican al libro.
Arquitectura · 10 nodos · 2 flujos
1Base de apuestas y calificación → Worker de calificación de juegosUn juego finalizado o cancelado se encola
Servicio / cómputo
Almacén de datos
Cola / mensajería
Sistema externo
Síncrono
Asíncrono / bucle
Desplázate hacia los lados para ver todo el diagrama
Cómo fluye, paso a paso
Haz clic en un paso para saltar a él. Haz clic en un componente para ver detalles.
Qué hace
Motor multi-tenant de back-office y liquidación para el producto en vivo de un operador de apuestas deportivas en línea. Califica apuestas live simples y parlays al finalizar los juegos, publica la contabilidad en flujos Kafka por tenant, audita la integridad de las cuotas y sirve configuración de límites, reportes y una UI administrativa en Blazor.
El problema
Las apuestas en vivo generaban un alto volumen de apuestas efímeras que debían calificarse exactamente como en el libro heredado, sin doble liquidación, entre varios tenants y con estricta corrección financiera. El enfoque heredado era un flujo de calificación único y fuertemente acoplado, sin reintentos ni dead-letter y con poca visibilidad de discrepancias.
Qué construí
Construí un pipeline de calificación con cola en base de datos: un trigger de fin de juego ejecuta un procedimiento de calificación, encola apuestas y un worker liquida la contabilidad en transacciones SERIALIZABLE para proteger los saldos.
Añadí un worker estilo outbox que agrupa apuestas calificadas (50 por mensaje) en tópicos Kafka por tenant, reduciendo los viajes al broker en aproximadamente 98 por ciento frente a un mensaje por apuesta.
Implementé un modelo de consumo Kafka en tres niveles (tópico principal, tópico de reintento con backoff exponencial y tópico dead-letter con alertas por chat) tras una abstracción genérica de handlers.
Garanticé calificación idempotente mediante seguimiento único de grupos de apuestas y concurrencia optimista, y validé resultados contra el sistema heredado con una CLI de comparación que reveló variaciones de redondeo en parlays reducidos.
Entregué una familia de workers programados: ingesta de marcadores con dead-lettering, derivación y reconciliación de timelines, tablas de hechos semanales de mejores jugadores y hold percentage, y un auditor de integridad de líneas que compara cada apuesta aceptada con datos de mercado archivados.
Entregué una UI administrativa modular en Blazor (diez bibliotecas de componentes) con tema configurable por tenant y caché en Redis, además de endpoints de reportes que responden en menos de dos segundos desde hechos precalculados.
Decisiones clave y por qué
01
Cola en base de datos para calificación, Kafka para distribución
La calificación debe ser atómica con la actualización de saldos, por lo que la cola vive en el mismo almacén transaccional que las apuestas. Kafka se usa solo tras la liquidación para distribuir resultados a los tenants, donde basta entrega al menos una vez con consumidores idempotentes.
02
Tópico de reintento y dead-letter en lugar de bucles de reintento en sitio
Los mensajes fallidos salen de la ruta principal para que un mensaje venenoso no bloquee una partición. El backoff se aplica en el tópico de reintento y los fallos permanentes se comunican a operadores con contexto.
03
Agrupación en el worker outbox
Los mensajes de una sola apuesta saturaban el broker en picos. Agrupar 50 apuestas por mensaje y por tenant preservó el orden por tenant y multiplicó el rendimiento.
04
Los workers nunca tumban el host por datos malos
Los handlers devuelven una disposición explícita (confirmar, reintentar, dead-letter). Los errores permanentes de datos se envían a dead-letter y se confirman, los de infraestructura se reintentan y un endpoint de salud expone la última marca de éxito para que el monitoreo decida reinicios.
05
Hechos semanales precalculados para reportes
Agregar apuestas liquidadas bajo demanda era demasiado lento. Workers programados recalculan una ventana móvil para absorber calificaciones tardías, de modo que la API de reportes sirve tablas de hechos indexadas en segundos.
06
Clean Architecture con tipos Result
Las capas de dominio, aplicación, infraestructura y API se registran mediante métodos de extensión y las operaciones de negocio devuelven valores Result en lugar de excepciones, manteniendo explícito el mapeo de errores y simples las pruebas unitarias.