Skip to content

feat(gamification)!: pay the daily streak as a milestone rakeback rate and fixed rewards - #407

Open
marek-chmielowski-blurify wants to merge 4 commits into
devfrom
feat/streak-milestone-rakeback
Open

marek-chmielowski-blurify wants to merge 4 commits into
devfrom
feat/streak-milestone-rakeback

Conversation

@marek-chmielowski-blurify

Copy link
Copy Markdown
Collaborator

Summary

  • The daily streak can be switched on and off; disabling ends every run and re-enabling starts everyone from zero.
  • Milestone days run 1-35 with no reset; past the last day the count keeps growing.
  • Each milestone can unlock a streak rakeback rate: a rate on theoretical GGR for a player with no rank, or a multiplicative uplift on rank instant rakeback.
  • Fixed milestone rewards unlock once per player, keep the terms captured at unlock, and are claimed as a bonus with rollover in the player's active currency.
  • Unclaimed rewards expire after a per-milestone claim window, settled by a new hourly promo-streak-expire job with one audit row each.

Why

The streak paid a mix of cash, random gift drops, a time-limited additive rakeback boost and bonuses, reset at a fixed day, and re-paid milestones on every new run. Operators need a simpler, cost-controlled model: a persistent rakeback rate while the streak holds, one-time fixed rewards, and a claim window, all configurable without a deploy.

Diagram

sequenceDiagram
  participant W as Wallet bet
  participant R as RakebackService
  participant S as StreakService
  participant P as StreakPayoutService
  W->>R: settled real-money stake
  R->>R: active rate = highest milestone <= current (streak live, enabled)
  R-->>R: ranked: base x rate x (1 + uplift) / no rank: GGR x rate
  W->>S: recordWager (after rakeback)
  S->>S: day reaches target -> current + 1
  S->>S: day in fixedRewards -> grant row (amount, rollover, expiry captured)
  Note over P: player claims before expires_at -> bonus in active currency
  Note over P: hourly promo-streak-expire -> unclaimed rows settle as expired
Loading

Alternatives considered

  • Keep the additive boost and add a multiplier beside it: two rakeback adjustments would interact and double-pay; replaced instead.
  • Drop the retired columns in this release: a rolling deploy would break old pods writing bets, so the migration is expand-only.

Risks

  • Breaking contract change (StreakConfigSchema, PlayerStreakSchema, accrual admin row); consumers must adapt before bumping.
  • The conversion migration switches any existing streak config off, maps bonus rewards to fixed rewards, and settles waiting grants with no matching reward as expired without audit rows (SQL migrations cannot write them). Check for waiting grants before deploying.
  • Retired columns (promo_streak_config.milestones, reset_after_day, promo_player_rank.rakeback_boost_*) stay unread; a follow-up release drops them.

Marek Chmielowski added 2 commits November 6, 2026 13:51
…e and fixed rewards

The streak no longer resets at a set day and no longer pays cash, gift drops or an additive
rakeback boost. A switchable daily casino streak counts days from 1 with no ceiling, and each
configured milestone day unlocks two separate things.

A rakeback rate row: a ranked player's rank rakeback is multiplied by one plus the row's uplift,
and a player holding no rank earns the row's unranked rate on the bet's theoretical gross gaming
revenue (the house edge, whatever the rakeback basis). The rate is read from the current config
when each bet settles, only while the last qualifying day is today or yesterday in UTC, and only
on the streak's products, so the bet that unlocks a milestone earns the previous rate. The accrual
row records the formula and percentage the streak applied; the additive boost column is written
as zero.

A one-time fixed reward: unlocked once per player per day (only a same-day rollback of the
unlocking day lets it unlock again), with the amount, rollover and claim window captured at
unlock. A claim after the window is refused, an hourly sweep settles unclaimed rewards as expired
with one audit row each, and a claimed reward becomes a bonus in the player's active currency
priced from dollars at claim time, with a rollover window as long as the claim window. Disabling
the streak stops counting and the next daily close resets every run; rewards already unlocked stay
claimable. Self-exclusion and cooling-off forfeiture is unchanged.

Contract changes: the streak config, the player streak response (now answers a disabled state
instead of a not-found error when nothing is configured) and the rakeback accrual admin row. The
config save keeps requiring write access to bonuses and now audits the client as well as the
staff identity.

Migration: expand only. New columns are added and the existing streak config is converted
(switched off, bonus rewards become fixed rewards, no rate rows, waiting rewards take the matching
fixed reward or settle as expired). The retired milestone and reset columns and the rank row boost
columns are kept unread and unwritten so a rolling deploy never queries a missing column; a later
release drops them.
Adds ADR-0051 for the multiplicative uplift, the rate for a player with no rank and the
once-per-player fixed rewards, notes on ADR-0048 that its additive boost formula is retired, and
describes the daily streak in the gamification module page.
Marek Chmielowski added 2 commits November 6, 2026 15:04
The set-config route takes the streak config schema directly instead of a second export that was
only an alias of it.
…fication

The event announcing an unlocked streak reward now carries the amount captured at unlock, in
dollars, and the notification maps it into both its params and its data next to the day, so a
consumer can say how much is ready to claim. The amount is required on the event and on the
notification param keys.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant