Remote config
Some game rules can change from the server, without a store release: the ad caps, the daily first-win gold, the weekly event’s prizes, a scale on every career prize, and a pause switch for six features. They live in Cloudflare Flagship (feature flags read inside the worker), app neon-drag (id 6e85360e-73cf-4822-a2fd-016bf566cf74), in the Cloudflare dashboard under Compute > Flagship. Flagship is an open beta since 2026-05-26 with no published pricing yet (docs: https://developers.cloudflare.com/flagship/, read 2026-11-12).
The two flags
Section titled “The two flags”| Flag | Holds | Split? |
|---|---|---|
live-config |
JSON with only the values that differ from the defaults | yes: a split is an A/B test |
paused |
JSON list of paused features | never |
live-config fields and their defaults (LIVE_DEFAULTS in src/game/core/liveConfig.ts):
| Field | Default | Used by |
|---|---|---|
fuelAdsPerDay |
3 | fuel ad (player/fuel/fuel.ts) |
goldAdsPerDay |
3 | gold ad (player/gold/freeGold.ts) |
dailyWinGold |
10 | the day’s first career win |
dailyBonusMax |
3 | daily cash bonus (player/ads/dailyBonus.ts) |
dailyBonusShare |
0.25 | the bonus as a share of the average event prize |
weeklyRewards |
[{tokens:1,gold:10},{tokens:1,gold:15},{tokens:2,gold:25}] |
weekly ladder, one per rung (always 3) |
prizeScale |
1 | every career prize, rounded to $10 (scaledPrize) |
A field of the wrong type or out of range keeps its default, field by field (mergeLiveConfig), so a typo never breaks a rule. prizeScale also moves what follows the average event prize: the daily bonus, quick race pay and the gold-to-cash rate.
paused features: online (rooms and the room list), weekly, ads (rewarded ads), goldPacks, friends, leaderboards. A paused feature’s button stays in place, disabled, and a tap says it is paused (ui/pausedFeature.ts); the race server refuses its requests with 403 and the same text. Two exceptions: a paused ad offer simply does not show (as when no ad is loaded), and paused gold packs are only no longer sold; a pack already paid for is still credited. paused is its own flag because requests before sign-in (the public leaderboard, online rooms) carry no user id, and Flagship would bucket them at random in a split.
How it flows
Section titled “How it flows”- Every request to the worker runs inside
withLiveConfig(party/src/liveConfig.ts): both flags evaluated for no one, then, once the session is known,live-configagain for the player (usePlayerConfig, context{ userId }). A worker serves requests side by side, so each keeps its own copy in anAsyncLocalStorage; the shared rules read it withliveConfig(). GET /api/configreturns{ config, group }: the merged config and the variation served, the player’s A/B group (defaultoutside a test).- The game fetches it at start, after the garage (
player/account/liveConfigFetch.ts), so the menus show it. Until then, and offline, the game shows the defaults; the server judges with its own copy either way. - When Flagship fails, the defaults hold.
Changing a value
Section titled “Changing a value”In the dashboard, edit the default variation of live-config, for example {"goldAdsPerDay": 4}. Or with wrangler from party/:
npx wrangler flagship flags update 6e85360e-73cf-4822-a2fd-016bf566cf74 live-config -t json --set-variation 'default={"goldAdsPerDay":4}'npx wrangler flagship flags update 6e85360e-73cf-4822-a2fd-016bf566cf74 paused -t json --set-variation 'none=["online"]'Changes reach the worker within seconds, no deploy. Flagship keeps an audit trail of every change.
An A/B test
Section titled “An A/B test”Add a second variation to live-config and a rule that serves it to a share of players, bucketed on userId:
npx wrangler flagship flags update 6e85360e-73cf-4822-a2fd-016bf566cf74 live-config -t json --set-variation 'more-gold-ads={"goldAdsPerDay":5}' --rule 'serve=more-gold-ads; rollout=50%@userId'The same player always gets the same variation while the rule stays the same. The group is in GET /api/config (liveConfigGroup() in the game) and on every analytics event (ab_group); npm run stats compares the groups (Game statistics).
Local checks
Section titled “Local checks”wrangler dev reads a local flag store, empty unless filled, so it runs on the defaults. Fill it with npx wrangler flagship flags pull <app id> or edit it with --local on the flag commands; both refuse while a dev session of the worker runs.