Corporate project · Presented company-agnostic: architecture and decisions only.
Live Betting Real-Time Engine
Multi-tenant grading, limits and settlement workers for live sports betting
Status
In production
Role
Senior backend engineer: architecture, grading and accounting workers, Kafka resilience, SQL grading procedures, reporting workers, Blazor admin UI and CI/CD.
Architecture
Database-queue grading pipeline
Serializable settlement
50 wagers per Kafka message
Retry tiers and dead-letter
Idempotent ledger writes
A finished game is graded, wagers are settled, batched per tenant and applied to the ledger.
Architecture · 10 nodes · 2 flows
1Wagering & grading database → Game grading workerFinished or cancelled game is queued
Service / compute
Data store
Queue / messaging
External system
Synchronous
Async / loop
Scroll sideways to see the full diagram
How it flows, step by step
Click a step to jump to it. Click a component for details.
What it does
Multi-tenant back-office and settlement engine for an online sports betting operator's live product. It grades live straight and parlay wagers when games finish, posts accounting to per-tenant Kafka streams, keeps odds integrity audits, and serves limits configuration, reporting and a Blazor administration UI.
The problem
Live betting generated a high volume of short-lived wagers that had to be graded exactly like the legacy ledger, without double-settling, across several tenants and with strict financial correctness. The legacy approach was a single, tightly coupled grading flow with no retry or dead-letter handling and little visibility into discrepancies.
What I built
Built a database-queue grading pipeline: a game-finished trigger runs a grading procedure, enqueues wagers, and a grading worker settles accounting inside SERIALIZABLE transactions to protect player balances.
Added an outbox-style worker that batches graded wagers (50 per message) into per-tenant Kafka topics, cutting broker round trips by roughly 98 percent versus one message per wager.
Implemented a three-tier Kafka consumption model (main topic, exponential-backoff retry topic, dead-letter topic with chat alerting) behind a generic message-handler abstraction.
Guaranteed idempotent grading using unique bet-group tracking and optimistic concurrency, and validated results against the legacy system with a dedicated comparison CLI that surfaced rounding variances in reduced parlays.
Delivered a family of scheduled workers: score ingestion with dead-lettering, timeline derivation and reconciliation, weekly top-player and hold-percentage fact tables, and an odds line-integrity auditor that compares each accepted bet to archived market data.
Delivered a modular Blazor admin UI (ten component libraries) with a tenant-configurable theme and Redis-backed caching, plus reporting endpoints that answer in under two seconds from precomputed facts.
Key decisions and why
01
Database queue for grading, Kafka for fan-out
Grading must be atomic with balance updates, so the queue lives in the same transactional store as the wagers. Kafka is used only after settlement to distribute results to tenants, where at-least-once delivery with idempotent consumers is acceptable.
02
Retry topic and dead-letter instead of in-place retry loops
Failing messages move off the hot path so one poison message cannot block a partition. Backoff is applied on the retry topic and permanent failures are surfaced to operators with context.
03
Batching in the outbox worker
Single-wager messages saturated the broker at peak. Batching 50 wagers per message per tenant preserved ordering by tenant while multiplying throughput.
04
Workers never crash the host on bad data
Message handlers return an explicit disposition (commit, retry, dead-letter). Permanent data errors are dead-lettered and committed, infrastructure errors retry, and a health endpoint exposes last-successful-message time so monitoring decides about restarts.
05
Precomputed weekly facts for reporting
Aggregating settled wagers on demand was too slow. Scheduled workers recompute a rolling window to absorb late gradings, so the report API serves indexed fact tables in seconds.
06
Clean Architecture with Result types
Domain, application, infrastructure and API layers register through extension methods, and business operations return Result values instead of exceptions, keeping error mapping explicit and unit tests simple.