Designing Data-Intensive Applications
Case 7

Turns, Timers, and Async Play

Wordle, chess, and daily puzzles mix turn order, deadlines, and optional async moves.

Puzzle games stress correctness over microseconds. A illegal word guess must be rejected; a daily puzzle must not accept two submissions from the same account.

Wordle at scale

One puzzle ID per calendar day, stored as immutable answer hash. Client submits guess; server returns tile feedback without leaking future answers.

typescript — Daily puzzle idempotency
// One submission per user per puzzle day
async function submitGuess(userId: string, puzzleDate: string, guess: string) {
  const existing = await db.submissions.findUnique({
    where: { userId_puzzleDate: { userId, puzzleDate } },
  });
  if (existing) return existing; // idempotent replay
  const feedback = scoreGuess(puzzleDate, guess);
  return db.submissions.create({ data: { userId, puzzleDate, guess, feedback } });
}
Key Takeaways
  • Turn state machine: WAITING → ACTIVE → COMPLETED per player.
  • Server validates moves against rules before applying to board.
  • Timers use scheduled jobs (SQS delay, Redis TTL) to forfeit on timeout.
  • Async mode: push notification when opponent moves.
  • Daily puzzles: same seed globally; validate once per user per day.
  • Smaller payloads than FPS — HTTPS and WebSocket both fine.
turn-basedstate machinetimerdaily puzzlevalidation