Weighted draws and explaining why someone won

More referrals should mean a better chance, but a draw is only fair when I can explain exactly what went into it.

2 min read

One of the ideas behind CrowdRelay was simple: a verified referral gives you an extra lottery ticket. Someone who brought twenty real people should have a better chance than someone who brought one. Fair enough.

Draws that change mid-run

Then I asked a less comfortable question: what exactly happens if a new referral is verified while the draw is running?

Reading the current counters and picking a weighted winner looks fine until two workers start the same draw, a late verification changes somebody's weight halfway through, or the organiser needs to explain the result a week later. "The database said so at the time" isn't a satisfying audit trail.

Freezing the input

So I freeze the input first. Every draw stores an immutable snapshot of eligible participants, their ticket counts and the rules used to calculate them. Winner selection runs against that snapshot instead of live counters. A referral verified five seconds later can join the next draw, but it can't change the one already in progress.

That also made the system much easier to reason about. I can tell who was eligible, how many tickets each person had and which version of the rule was used. The random part is still random, but the input is fixed.

One reward ledger

The same reward ledger handles everything else. Three verified referrals may issue a discount. A weighted draw may select several winners without replacement. An operator may grant a manual reward after fixing a mistake. A physical prize may wait for fulfilment, while an admission pass can later be claimed at the door. Different rules decide what should happen, but every reward gets a stable identity and a visible lifecycle.

Retries

Retries needed the same treatment. A browser can time out after the transaction commits. A worker can restart at exactly the wrong moment. Retries can't be eliminated, so durable operations get stable idempotency keys. The first execution records the result and the next one returns it. No extra ticket, no second coupon, no accidental second winner.

A lottery mechanic is easy to demo. Making a draw survive retries, concurrent workers and an organiser asking difficult questions took more work, and that's the part I find more interesting.

Loading…