The Crowded Total
The home team scores late, and a few thousand bets land on the same outcome in the same second.
Late in the game. Liability on a home win is $180K, against a $250K cap.
Where this shows up
Why the stream job gets it wrong
Liability is a sum over every accepted bet on an outcome, so a stream job keeps it running and publishes it for the bet checks to read. That works until a few thousand bets arrive in the same second. Each check reads the published total, none of them can see what the others are accepting, and the stream job is still counting when they all say yes.
By the time the decision ran, its context was outdated. We call that a context gap.
Check each bet against the bets accepted a moment before.
Accepted bets are written to Tacnode, and each bet check reads liability computed from them, including the ones accepted a moment earlier. The bets and the total live in the same place, so the cap holds when the burst arrives.
If an engineer asks how
Accepted bets are held in Tacnode with ACID semantics, so concurrent acceptances against the same cap are serialized. Liability is a query over those bets at the latest committed data.
Questions to put to your team
- When a thousand bets hit the same market at once, how do you enforce the liability cap?
- How far behind the accepted bets is the total your bet check reads?
- Has a big game ever ended with liability past the cap?
Is your liability total telling this lie?
Bring it to a demo, and we’ll trace what it reads and how old that data is by the time it runs.
Book a demo →