Real-time games have a habit of turning simple UI events into distributed systems problems. A player taps a cell. Another tab reconnects. A stale WebSocket event arrives from the previous round. The user taps again before the first request finishes. If the server treats those as independent "claim" and "unclaim" commands, the board can drift. I ran into this while building BingWow , a browser-based multiplayer bingo game. The product looks simple: every player has a board, taps squares, and wins by completing a row. The data model behind that simple interaction has to answer one question perfectly: after this tap, which clue ids are currently claimed by this player in this round? The bug-prone version The first version had separate endpoints: POST /api/game/claim POST /api/game/unclaim Enter fullscreen mode Exit fullscreen mode That matched the UI state. If a square looked unclaimed, the client called claim . If it looked claimed, the client called unclaim .…