630 MB
holds every live game at peak
About 5 million games a day; assume a 3× evening peak. That’s 63,000 live games at 10 KB each. One machine’s memory holds them all.
Who owns a live game?
Bad: Database on every move
28,000 database operations a second, races, and a flag sweeper.
Good: One actor in memory
One message at a time. No locks, no reads; a timer catches flags.
You thought for 1,000 ms. The server measured 1,150.
Timed by arrival, Chennai pays 150 ms a move, 6 of 60 seconds over 40 moves. So the server refunds the measured lag.
But your app reports the thinking time. A modified client could invent lag.
The trick
Refund lag only from a per-player quota that refills each move. Steady lag is free; invented lag is capped.
A tunnel swallows the reply to your move. Resend it?
Every move carries its ply, every event a version. Ply 16 already holds g1f3, so the resend changes nothing and you get the v42 you missed.
First come, first served pairs a 900 with a 2200.
Instead, every 12 s in 1+0, pick the pairs with the lowest total cost, the rating gap minus a bonus per missed wave.
100,000
live viewers on one world-championship game
One move to all of them is 20 MB. So the actor publishes once; socket servers fan out, and a relay streams top games through a CDN.
A restart must never decide a game
- Flush every actor before shutdown
- Re-create each game on its new owner
- Clients resume from their last version
- If a clock expired meanwhile, abort the game
Remember
One in-memory actor owns each game and its clock, refunding lag from a bounded quota. Plies and versions make resends harmless. Pair in waves, fan out once, and never let a restart decide a game.