I turn Game Server Project into a Product

Wildan Fathan
4 min readMay 4, 2024

From my experience, choosing game server is hard. It is either easy-but-costly or affordable-but-full-of-hassle. Former options include Amazon GameLift, Firebase, and Pusher. These services give you easy access to game servers and let you focus on your business. However, if you’re not very careful with the game design, you could end up with huge bills. The alternative is to build your own game server. This approach eliminates the need for monthly payments to a vendor. However, you’ll then be responsible for maintaining the server and ensuring its constant uptime, which requires significant attention. That’s why I created GenGame, an open-source game server that scales well.

I’ve created many games with multiplayer features in the past. I usually handle the backend. I used NodeJS, PHP or some 3rd party, in the past. The clients are happy most of the time. Until one day one of our client made a request to me and the team that they want to scale the server because they found some players lagging. It was for IO game, think like Agar IO. We built it with NodeJS. The problem with NodeJS is they run on single thread, it means that it doesn’t care how many CPU you have on the machine it always use one only. We can however make it multithreaded but we need to design the system carefully and it always has unecessary overhead. Back to the story, after optimizing here and there like reducing tick rate, rewrite the logic with C, the server can still only handle N concurrent connection. So I did research whether there is technology that is accessible, scalable, and not vendor lock, then we found Erlang.

I started creating GenGame in 2021 to proof whether Erlang VM can handle common use case of backend game server. It was very simple, it handles player movement, damage handler and health point handler. I tested it with Unity as a client, and unsurprisingly it runs well. Actually there was a time where I separate the services into 3 projects: app, API and world. But it doesn’t end well because we have to maintain 3 services instead of one. That’s why on the current version I revert it back, so it become single service. It was my mistake by making it over-engineered. Beside that, documentation on the first version talk too much about implementation detail and failed to answer: what, why and how. I forgot that people with their business who want to adopt a game server couldn’t care less about system architecture or whether the tool use event driven, instead they do care if the tools can help their business to achieve the goal. So, in the current version I update the documentation to answer what is GenServer, why you should use it, and how to use it.

So what features does GenGame provides?
- Multiplayer relay service
- Server authoritative: RPC and hooks
- User authentication
- Client library: Unity and WebSocket
- Matchmaker

I’d like to add other features in the futures:
- Friends
- Leaderboards
- Chats
- Support more client like Unreal Engine, Godot, etc

Multiplayer relay is basically lets a player send data directly to other player or broadcast it to all the players in the same match session without any server interference, the server will send the data as-is. We can use multiplayer relay for something that’s trivial or actions that doesn’t affect the gameplay like changing player cosmetic. While server authoritative means server doing some calculation before sending it to the client. Server authoritative method used for actions that is need authorization like purchasing item, hitting enemy or actions that initiated by the server like spawning enemies. GenServer can do both. Currently server authoritative can be written in Elixir, JavaScript and Rust.

Anyway, we haven’t talk about performance. GenServer is built on top of Phoenix framework. It can handle huge load at the same time. Once, there was a developer that achieved 2 million WS connection in a single box with Phoenix Web Framework by squeezing everything that can be optimized. Read the story here. Although I don’t try optimize the framework, its performance is still excellence. I did try to benchmark GenGame with Tsung. I spawn GenGame in a server with 2 CPU and 4GB memory. Then I setup few thousand clients that tried to connect to the server at the same time. The client joined to topic called benchmark:ccu. After it’s connected, I let them idle for 200 seconds before disconnected. Here is the result:

We can see that around ~20k concurrent connection can established. You can try yourself at home, the script is here. I’m quite happy with the result even it can be optimized more. To compare with Pusher, we need to pay $899/month to get 20k concurrent connection, while I only use single VPS in DigitalOcean that cost ~$28/month, ofcourse we need to setup many other things to be ready for production.

Conclusion

Building game server is complex task. That’s why we should be standing on the shoulders of giants by using existing tools that is already established like Erlang VM and Phoenix. Then from there we can start building business logic from ground up.

Photo by Roméo A. on Unsplash

--

--