A production-grade, event-driven backend architecture for real-time and turn-based multiplayer games. Designed for scalability, fault tolerance, and clean domain separation.
This system is suitable for games such as:
- Tic-Tac-Toe / Chess / Checkers
- Turn-based strategy games
- Real-time competitive games (with different state models)
The system is built as a set of decoupled microservices communicating through events.
Clients
|
WebSocket Gateway
|
RabbitMQ (Event Bus)
|
------------------------------------------------
| Player Service | Matchmaking | Game Service |
------------------------------------------------
|
Redis (Hot State)
|
MongoDB (Persistent State)
- Single responsibility per service
- Event-driven communication
- Redis for real-time state
- MongoDB for persistence
- Stateless services
- Horizontal scalability
Responsible for:
- WebSocket connections
- JWT authentication
- Message validation
- Publishing events to RabbitMQ
- Pushing events to connected clients
It does not own business logic or domain state.
Owns:
- Player profiles
- Ratings / ELO
- Presence (online, offline, in-game)
- Reconnection handling
Acts as the single authority for player state.
Responsible for:
- Player queues
- Skill-based matching
- Match creation
- Queue timeouts
Produces:
match.createdmatch.cancelled
Owns:
- Game rules (Tic-Tac-Toe turn validations)
- Turn validation
- Win / lose / draw logic
- Timers
- State transitions
Uses Redis for atomic game state and MongoDB for history.
Provides:
- User Registration / Sign-In pages
- Real-time matchmaking queue wait state panels
- Interactive game board grid with synchronized turn timers
- Active match emoji and text chat interface
- Historical match review explorer and profile settings dashboard
Used for:
- Active game state
- Player presence
- Timers
- Queues
Patterns:
- Hashes for state
- Sorted sets for timers
- Lua scripts for atomic moves
- TTL for cleanup
Used for:
- Match history
- Player statistics
- Replay data
- Auditing
All services communicate via RabbitMQ.
player.connected
player.disconnected
match.created
match.ended
game.cmd.move
game.event.turn
Events are:
- Immutable
- Idempotent
- At-least-once delivery
Each event includes:
{
"eventId": "uuid",
"type": "game.cmd.move",
"timestamp": 123456789,
"payload": { ... }
}- Player connects →
player.connected - Player joins queue →
matchmaking.enqueue - Match created →
match.created - Game initialized in Redis
- Players send moves →
game.cmd.move - Game Service validates + updates
- State broadcast →
game.event.turn - Match ends →
match.ended - Results saved to MongoDB
- Ratings updated
The system is resilient to:
- Service restarts
- Network partitions
- Duplicate events
- Client disconnects
Mechanisms:
- Redis TTL cleanup
- Event idempotency
- Dead-letter queues
- Reconnection windows
- Stateless services
Every component can scale horizontally:
| Component | Scaling |
|---|---|
| Gateway | WebSocket sharding |
| RabbitMQ | Clustered |
| Services | Stateless replicas |
| Redis | Cluster |
| MongoDB | Replica sets / sharding |
Supports:
- Tens of thousands of concurrent players
- Millions of events per day
- JWT authentication
- No direct client → service access
- All state changes go through Game Service
- Rate limiting on Gateway
- Event validation on consumers
- Docker
- Docker Compose
- Node.js / Go / Python (depending on implementation)
Start the service infrastructure and backend microservices using the root docker-compose.yml definition:
docker-compose upServices:
- Gateway →
ws://localhost:8080/ws - RabbitMQ →
localhost:5672 - Redis →
localhost:6379 - MongoDB →
localhost:27017
{
"type": "GAME_MOVE",
"data": {
"matchId": "abc123",
"move": "A1"
}
}{
"type": "GAME_STATE",
"data": {
"board": ["X", "", "O"],
"turn": "player2"
}
}This project prioritizes:
- Correctness over shortcuts
- Explicit domain ownership
- Observability
- Real-world failure modes
- Clean scaling paths
This is not a toy architecture. It is designed to survive production.
- Spectator service
- Match replays
- Analytics pipeline
- Anti-cheat detection
- Regional matchmaking
- Federation / cross-cluster play
This backend is ideal for:
- Indie multiplayer games
- Competitive platforms
- Real-time learning apps
- Multiplayer simulations
- Game backend experimentation
Real-time systems fail in silence. This architecture is built to fail loudly, recover automatically, and scale predictably.
MIT / Apache 2.0 (your choice)
This project demonstrates a real distributed system, not just a game.
If you understand and can implement this architecture, you are already operating at a professional backend engineer level.
