algomiBlogs
← All posts

Designing an Online Chess Game: Rules First, Servers Second

Algomi Research · Created 2026-09-16 · Updated 2026-10-15 · System Design

System Design Case Studies · Part 10 of 15
Designing a Professional Network: People, Connections, and FeedsDesigning BookMyShow: Selling Each Seat Only Once While Thousands Rush In
Page 1 of 1

The inter-school final, played online

Meenakshi in Chennai and Arav in Delhi meet in the final of an inter-school online chess championship: 10 minutes each, plus 5 seconds a move, on ShatranjOnline. Three hundred classmates are watching. In the space of one game, Meenakshi's Wi-Fi double-sends a move, her screen shows 3 seconds left when the server says her flag fell, and the server hosting their game is replaced mid-match. (Meenakshi, Arav, ShatranjOnline, Tarun and every number here are made up for teaching.)

Tarun built ShatranjOnline. His design rests on one idea. Two classmates playing over the board can call a referee to decide whether a move is allowed. Online, the server is the referee. A player's screen may suggest a move, but only the server decides whether it's legal and records the result.

The problem has two layers:

  • Low-level design organises the board, pieces, moves and rules.
  • System design keeps a shared game correct when messages repeat, players disconnect or servers fail.

The scope is standard two-player chess with move history and optional clocks. Matchmaking, ratings, computer opponents and tournament administration are separate. Choose and document the online rules you apply: platforms don't all use the same time and draw policies.

What happens in the final Idea it forces
"Could a modified client move a rook through pieces?" The server is the referee
"Same board picture, but castling is no longer allowed" The full position state
"A pinned rook was allowed to move" Legal vs pseudo-legal moves
"Is it a draw, or does someone have to claim it?" Knowing when a game ends
"Meenakshi's move was sent twice" Command IDs and versions
"Her screen said 3 seconds; the server said time's up" The server owns the clock
"The game's server was replaced mid-match" Ownership and fencing

In 30 seconds, as an architect would frame it: "I keep a deterministic rules engine separate from transport and storage. The server holds the full position: placement, side to move, castling and en passant rights, counters, repetition history and clock. Each game has one owner that serialises commands. A move carries a command ID and the version it was based on, and it is validated, applied, clock-charged and committed atomically, then pushed to both players. The server owns the clock, and a fencing generation stops a replaced owner from committing. Games are independent, so they scale out by game ID."

1. "Same picture, different game": a board picture isn't the full state

Mid-game, Arav's king and rook are back on their starting squares, but they moved earlier and came back. The board looks exactly like the opening position, yet Arav can no longer castle.

State Why it matters
Piece placement Where pieces currently stand
Side to move Which player may act
Castling rights Whether relevant king and rook movements removed the right
En passant information Whether a special pawn capture is available now
Move counters and position history Draw rules and history
Clock state Remaining time and authoritative turn timing
Game status and result Whether more moves may be accepted
State version Detect stale or repeated commands

Reading the table. Only the first row is "the picture." Every other row is information the picture can't show, and every one changes which moves are legal or how the game ends. Two positions with identical pieces can allow different moves, because their histories differ.

Initialise the complete standard position, not just kings and queens. Use one coordinate convention everywhere, such as files a to h and ranks 1 to 8.

2. Give each object one job

classDiagram
    direction TB
    class Game {
        gameId
        version
        status
        applyCommand()
    }
    class Position {
        pieces
        sideToMove
        castlingRights
        enPassantTarget
    }
    class Move {
        fromSquare
        toSquare
        promotionChoice
    }
    class RulesEngine {
        legalMoves()
        applyMove()
        evaluateResult()
    }
    class Clock {
        remainingTimes
        turnStartedAt
    }
    Game *-- Position
    Game *-- Clock
    Game --> RulesEngine
    RulesEngine --> Move
    RulesEngine --> Position

Reading the diagram. A filled diamond (*--) means "owns": the Game owns its Position and its Clock, and they don't exist without it. A plain arrow means "uses": the Game asks the RulesEngine whether a Move is legal in a Position.

The key design choice is that the RulesEngine is deterministic: the same position and move always give the same result. It knows nothing about networks, databases or time. The Game supplies identity, ordering and clock decisions around it.

This is a responsibility diagram, not a full implementation. A class per piece can explain local movement, but no piece alone has enough context to decide full legality. Moving a rook might expose its own king to check, so a central rules engine must evaluate the resulting position.

You've reached the free preview of this post.

Subscribe to the Blogs plan (₹99/mo) — or use any Algomi Suite, Career, Investor, or Trader plan — to keep reading.

See plans

Sources

System Design Case Studies · Part 10 of 15
Designing a Professional Network: People, Connections, and FeedsDesigning BookMyShow: Selling Each Seat Only Once While Thousands Rush In