</> MAANG.io
system design · 301

Advanced

Master system design interviews with scalable architecture patterns, distributed systems, and real-world design challenges.

0/480 solved 0% complete

Section 12: Beyond the Blitz Board - Follow-up Feature Evolution

Executive Summary: The product team has six asks: daily chess, variants and Chess960, play the computer, live broadcasts of over-the-board events, an opening explorer, and team battles. None of them needs a rewrite, because each one lands on a decision we wrote down with a flip trigger. Daily chess flips the single-owner actor choice: game actors hibernate and flag timers move to a durable scheduler. The explorer flips the archive choice: a derived index gets built in batch over it. Variants add rules engines and rating pools, and thin variant pools trip the matchmaker's thin-pool trigger. Bots, broadcasts and team battles flip nothing. Every API change is a new field or a new endpoint, and a v1 client keeps working.

The interviewer leans back. "The platform is fair and it's alive. Product wants more. How much of this survives?"

You: "Most of it. Before each feature I'll say which earlier decision it touches. If none, it's just new code on the old path."

The v1 core (game actor, gateway clocks, conditional write, game-ended) feeding six follow-up features, each labelled with the decision it touches: daily chess flips the single-owner actor so actors hibernate, variants add a rules engine and pools and trip the thin-pool trigger, play the computer flips nothing because a bot is a client, live broadcasts relax server authority to an arbiter, the opening explorer flips the archive choice to a derived batch index, and team battles keep the director, which aggregates teams

Daily Chess: The Actor Goes to Sleep

In daily chess you get days per move, not minutes per game. The single-owner actor choice said one in-memory actor owns each live game and arms its own timers, and its flip trigger named this exact case. An actor that sits idle for three days is a bad deal. It holds ~2 KB of memory to do nothing, and it uses up a slot under the 10K-games-per-node cap, a cap we set for blast radius. Worse, every deploy would turn into a failover of thousands of sleeping games.

So the actor hibernates. State lives only in live_games, and the item gets no owner_server while nobody is moving. When Omar opens the game and plays, his gateway asks placement for the owner and finds none. Placement then assigns one, bumping owner_epoch, and the new actor loads the item with one read. That's the Section 10 failover path, run on purpose. The move then goes through the same pipeline as a blitz move: validate, conditional write ply = :n AND owner_epoch = :e, publish. After an idle spell with no messages the actor unloads itself, so two players trading moves within minutes don't force a reload each time.

Timers can't live in memory for days, so they move to a durable scheduler: a table of (deadline, game_id, ply) entries, polled in deadline order. When an entry fires, the actor materializes and runs Section 7's flag check: is it still that side's turn at ply n? If a move got in first, the entry is stale and gets ignored. The scheduler can therefore fire at least once and the check absorbs duplicates. The same scheduler sends Notifications a reminder before the deadline, by push or email.

Interviewer: "What about gateway timekeeping?"

You: "It still runs, but it no longer matters. Gateway timekeeping exists so that 120 ms of backbone transit doesn't land on a three-minute clock. Against a three-day deadline it's noise, so the deadline is just the server's commit time plus the allowance. The rating pool is new too: daily gets its own."

Quick check before moving on:


Sign in to continue reading

The rest of this lesson is available with a free account. Signing in with Google or Microsoft is free.

Sign in to read the full lesson

Sign in to MAANG.io

Use your Google or Microsoft account — no password to remember.

Continue with Google Continue with Microsoft

Please accept the terms above to continue.