Multiplayer game server
Multiplayer games are always fun. Even if you’re not a gamer, joining a lobby and playing with your friends is never boring. But making a multiplayer game? Not so much.
As easy as it is to pick up a game engine and code a single-player action-adventure, adding multiplayer into the mix is not straightforward at all. There are game engines with built-in multiplayer networking support, as well as services and SaaS tools to manage game servers, but they all seem either too restrictive or a hassle to set up.
At least, that’s what I told myself to justify building my own multiplayer game server. So here I am, exploring how to make one.
In terms of basic requirements, all I need is a remote server that can exchange game state data across users in a shared game session. Latency will definitely play a huge role, but I think I can work around it if I focus only on round-based or turn-based games.
I’m choosing Elixir for this project—partly because I need an excuse to work with it.

Latency
For a real-time game latency matters a lot. If I add a constraint that the server is only suitable for round or turn based games then I can possibly get away with slower response times.
Capacity planning
Any good stack should be able to vertically or horizontally scale. For my design I plan to use in-memory server state for game sessions. This makes horizontal scaling not so straightforward. But for my use case I can just add this as a constraint and assume there will be no horizontal scaling. The vertically scaled server should be able to handle couple thousand sessions at the same time
Must have Features
- Host Game (predefined game templates)
- Share Game via link
- Join Game via link or code
- In-Game player chat
Good to have Features
- Custom Game Templates
- Game History
- Leaderboard

Data Structures
- Game templates
read only game definition that defines game rules, play conditions, win-lose scenarios
- Game instance
In memory instance of a game template that keeps track of the game session
- Game state
The game state at any given time. This should be same across all players and game servers. On concluding the game this may optionaly persist in the db
Game process
- Backend server should spawn a new process for an initiated game
- Game state must be kept in-memory for the lifetime of game
- Game state must be saved once game ends or gets interrupted

Game Loop

Sample game to test all functionalities
- No game master
- Min- max players (2-3)
- Round based
- Max round 5
- First player will create the game and gets the game ID
- Other player join game using the game ID
- Fourth player should receive a game room full message
- Once joined player will be asked to confirm that they are ready
- Once everyone is ready the game process will ask the question
What is the word?
- Correct answer is
bird
- If no one guessed the correct answer then the user with longest word length wins
- Max word length is 10
- Tie breaker is lexicographical sort
- If all answer with a word more than 10 then all loose
- Winner gets 10 points and loser gets 0 points
- All players will answer and then go into a state where they wait for other players to answer
- Once game receives all the answer it marks the round complete, calculates the score and broadcasts the message
- You win the round +10
- You lose the round 0
- After round 5 end the game and broadcast the score
- User 1: 0
- User 2: 40
- User 3: 10
- Winner User 2
Client options
CLI client with two options
Host Create the game and send back the game ID
Join Requires a gameId as argument Join the game if it exists Join the game if game room has space
Provide >
prompt for the user to answer
Clients
- JavaScript client for the web
- Kotlin client for android and CLI
Why choose Elixir
Developed as a corporate language back in the 80s to build the next generation of network switches it was designed to solve the following problems:
- Handle concurrent requests
- Handle production failures gracefully
- Update the deployments without downtime
Creating the template code
Setting up environment variables
- setup db
- create env variable file
source ../settings/.env.sh
Steps
- mix deps.get
- make sure .vscode settingn
"elixirLS.projectDir": "./server",
- MIX_ENV=dev mix phx.server
http://localhost:4000/
References
TODO
Dev setup (sample client and local server) Stress testing (RPS, maximum games) Production deployment