DEV Community

Cover image for Building a multiplayer game using WebSockets - Part 1

Building a multiplayer game using WebSockets - Part 1

sauravmh profile image Saurav M H Originally published at Medium ・6 min read

A definitive guide for building your multiplayer game on a browser the right way using on NodeJS and React. Ranging from folder-structure to project deployments

Getting started with a unique idea is important. But it is much more crucial to set the foot in the right direction when starting with a project.

"The future belongs to those who learn more skills and combine them in creative ways."

  • Robert Greene, Mastery

Why another tutorial?

This is very important to clarify. There are tons of guides online focusing on “Getting started with” and it gets more frustrating when all of them are chat apps. But here we will focus on “Getting started with building a scalable project using”, which is not a chat app :).

This guide will explain more about the Code Infrastructure rather than focusing on UI/UX. So bear with me if UI doesn’t look so appealing.

What is is an abstraction built over the WebSockets protocol. Websockets is a protocol that allows a bilateral synchronous exchange between a client and a server. Or a bi-directional communication pipe in simple words
Note: Here WebSockets and will be used interchangeably (even though they are different in some aspects) unless stated otherwise.

Why WebSockets and not HTTP?

For real-time multiplayer games, we require the client to send information packets to the server and server sending/broadcasting data simultaneously. This can’t be achieved using HTTP as the client has to send a request to the server to actually receive something. This isn’t a viable scenario for multiplayer games.

What do you mean by the “Right way”?

The Right way — here means getting started with a Codebase which can be easily scaled further, and simultaneously not creating much hassle for smaller projects. It addresses common practices that can be followed for a much more modular project. This in no manner states it is the official way to build WebSockets projects. But is simply my opinion on it, you can easily swap out bits and parts of the project you don’t like :D

What is the project about? ⚡⚡

So coming to the core of the guide. This guide explains building a “multiplayer game” through a real-world project. This way it is much easier to see the project in action and we know the code/infrastructure works too! The project is…

Multiplayer Football Draft Simulator

What does this game do? ⚡

It is a turn-based multiplayer game. Where people enter and create a room. Other people hop into the room. Then the game begins where all players are shuffled and first-person gets the chance to pick the football-player he wants. He can search from the list of players (viewing their stats, position, ratings, and other details) and confirm his selection within the allocation time. Now, the turn is passed to another player. This repeats until every person has picked their whole football squad.

Pretty simple? Yes/no, it doesn’t matter. We will see the detailed breakdown of the code infrastructure behind this.

Server Architecture ⚡⚡⚡


Game architecture

The above diagram explains how everything is connected from a birds-eye point of view.

Both the HTTP and Websockets server in this guide uses NodeJS. We are using Redis DB as supports its integration out of the box also the read/write operations are much faster as data is stored in-memory. MongoDB is used as a more permanent storage solution. The game results and the user teams for each room are stored in MongoDB after the end of each draft round. It also stores user credentials if they wish to register (this project has an optional registration/login step).

The WebCrawler is written in Python3, using the Scrapy library. The football players dataset has been crawled from It consists of more than 20,000 players including their rating, statistics, worth, clubs, etc. It also has an optional data-analysis jupyter-notebook for playing with the scraped data, but its discussion is out of scope for this guide.

The Folder Structure (ExpressJS + MongoDB +

NodeJS does not enforce code structure on you. This gives us a lot of flexibility to design them, but you can go horribly wrong which can lead to difficulty in maintaining and scaling the projects. This particular project structure can be used when working with sockets + NodeJS

Let's dive in how the project codebase is structured

├── controller  
│   ├── authController.js      # Handles authentication requests  
│   ├── searchController.js    # Handles search queries  
│   ├── userController.js      # Handles user profile operations  
│   └── ...  
├── database  
│   ├── db.js                  # Initialize DB connection  
│   └── ...  
├── middlewares  
│   ├── authenticated.js       # Decode and verify JWT token  
│   ├── error.js               # Common Error Handler  
│   ├── logger.js              # Control logging levels  
│   └── ...  
├── models  
│   ├── roomsModels.js         # DB model for rooms  
│   ├── usersModel.js          # DB model for users  
│   └── ...  
├── schema  
│   ├── rooms.js               # DB Schema for rooms  
│   ├── users.js               # DB Schema for users  
│   └── ...  
├── socker  
│   ├── roomManager.js         # Socket listeners/emitters handle  
│   ├── sockerController.js    # Control socket connections  
│   └── ...  
├── app.js                     # Entry file for the project  
├── env.js                     # Store environment variables  
├── routes.js                  # All routes initializer  
└── ...

The backend is divided into different directories according to the project requirement. If you want to skip or swap certain modules, it is as easy as adding another directory.

Most of the sub-directories are common to node projects, so I won't explain them in detail here. The comments beside each directory should give an idea of what it is.

We will focus more on subdirectory socker/. This the place where your core code will reside.

The entry point for (App.js)

Here two servers are created, app — listening to HTTP requests and server — listening to WebSockets connections. It is recommended to keep them connected to different PORTs to avoid confusion.

You might be wondering what is "socker" on line 1 and 8.

What is socker?

Socker is just a function alias (because I am building a football draft game here, duh!). This function attaches the Server (passed in line 8 of app.js) to an instance on a new http.Server. In simple words, it attaches the engine to the server passed to it.

But the above code doesn't explain much. Now, the following questions arise:

  • How do I interact with connected clients?
  • Where are namespaces?
  • Where are the Rooms/Channels?
  • Most importantly, where is the game?

Creation of Namespaces and why?

Namespaces are an important feature of It represents a pool of sockets connected under a given scope identified by a pathname like /classic-mode , /football-draft , /pokemon-draft , etc. This is basically creating different endpoints or paths. It allows us to minimize the number of resources (TCP connections) and at the same time separate concerns within your application by introducing a separation between communication channels. By default, connects to the/ namespace.

Creation of Rooms/Channels and why?

Within each namespace, you can create arbitrary channels or rooms. This further allows you to create connections which sockets can join or leave . Here we use channels to create different rooms where users can join or create to play together.

Example of joining a room

The join() operation checks if the required roomId is already created. If not, then it creates the room and adds the player to the given roomId. And if it is already created it joins the room directly.

A wholesome example summarizing the use of namespaces and channels:

That's it for Part I. The code structure shown here works for medium size projects quite well. If you are building a quick prototype, you may omit or combine the schema and models folder. Do not hesitate to make the project lighter if required :)

What if the project size increases? The current structure might not work well. You can create sub-folders as per required services and components ( user-authentication , __tests__ , analytics , etc.). You might even create microservices i.e. deploying each process or service individually allowing you to load-balance or scale only the processes under heavy-loads.

Remember do not over-engineer your product, build and deploy in stages!


Be it a joke or an engineering-project, no one likes overdoing it :)

If you are interested, here are my project links:

Next article/articles will focus on:

  • Creation and handling of rooms for each namespace.
  • A brief explanation of the client-side of the project (in ReactJS)
  • CI and Deployment of each project package.

Let me know if you have any questions or suggestions for future articled

✌️️ Have a great day!

Follow me on twitter @sauravmh for updates!

Discussion (19)

Editor guide
yandeu profile image

Have you already tried It allows client/server communication over UDP, which is perfect for real-time multiplayer games.
I'm the author of

sauravmh profile image
Saurav M H Author

I checkout out the project, it looks very promising.

But as mentioned in the docs itself, socketio is suggested over geckos for turn based multiplayer games (which is my current project) :D

Would surely look into this if there is any update for turn-based games. Other than that it's a great project!

yandeu profile image

You're right. For turn-based multiplayer games, which work fine with the limitations of TCP, there is no need for 👍🏻 is only needed for games that absolutely require fast communication, like a shooter game for example.

gdi3d profile image
Adriano Galello

This is great, is this going to be published on a GitHub repo also?

sauravmh profile image
Saurav M H Author

Thanks Adriano! Yes, it is and always will be open sourced. I have already linked the project at the end of the article :D

gdi3d profile image
Adriano Galello

Ohh cool, I didn't realize it was your own repo :P, sorry about that

sauravmh profile image
Saurav M H Author

Hey all 👋,

I wanted to make an announcement. It's been a year since I wrote this and I am very grateful that people are still using this as a reference. And I want people to use this even with the new and breaking changes from

There are a few changes made to the codebase, mainly in the way rooms and connections with a room are handled with the new release of library v4. As mentioned I had used some internal APIs but they are no longer supported with the new release.

But I have made those changes in my GitHub repository @fifa-api and even added support for Redis to help to scale. I would appreciate it if you would use the code from the Github repo directly than from the snippets here, as I don't want to change this code for people who are using this with older versions.

Thanks for understanding and have a great day ahead 🤠


Changelog for [github/fifa-api]

  • codebase synced for updated libraries
  • support for Redis added
  • Docker containerization support added
  • minor web app UI changes
kretaceous profile image
Abhijit Hota

Good write up. =)
Have been waiting for part 2 though!

sauravmh profile image
Saurav M H Author

Apologies for the delay 🙇

But good news, the next part is already half done! Super excited to share it with you guys 😋😋

Socketio game system design and their deployments on scale

P.s: I shouldn't have given the spoiler 🤫

kretaceous profile image
Abhijit Hota

🤩🤩🤩 Awesome! Thanks a lot!

udaraweerasinghege profile image
Udara Weerasinghege • Edited

This is awesome. Thank you for sharing. I have a few ideas for real time games, and will definitely be following this.

sauravmh profile image
Saurav M H Author

Thanks Udara! Stay tuned for the part 2, I hope it will help you complete your project with deployment

drakgoku profile image

where is part 2?

Thread Thread
sauravmh profile image
Saurav M H Author • Edited

Sorry, I got held up in some other projects. Should expect the part 2 by next week.

I'll try my best to avoid delays here!

longvd89 profile image

You can explain the game how play ? thanks

sauravmh profile image
Saurav M H Author

Sure! It's a turn-based multiplayer game. This game in particular allows you to build your own Football Team, by choosing players based on turns. You can search these football players based on any stats (their name, rating, team, positions, and a lot more!)

To play:

  • Create a room (add a password, if you wanna keep it private)
  • Share the room ID with your friends, and they can join the room
  • Once, all players are ready the draft begins
  • Each user can choose their player from the search box
    • Every turn has a time limit, so pick before the time runs out!
  • After you create your dream teams, use the same teams on your FIFA game and play with each other

This was created mainly for offline gaming, to avoid writing player lists manually on a paper or sending on chats when creating custom teams amongst a group of friends. Easily search and add players to your teams with this platform as a middleman :D

kenodek profile image
Dominik Targosz

What is the reason to treat adapter as store. Is it just your idea or some standard? Why not to store data in constructor?

sauravmh profile image
Saurav M H Author • Edited

Using socketio adapter as a store is a rather undocumented feature, which is used internally. So not entirely my idea 😉

And we do not use constructor for storing data, as we need persistent storage between users across a single room. With a constructor you will be saving info for each user separately (which is not intended here).

Yes, you can use global variable to store all the information about the room and its users. But using this solution, it won't be secure (as info about all rooms are exposed to the user, yes you can make it better by adding sanitizations and read protects yourself) and second it won't be scalable (as with sockeio-adapter case; using a redis adapter is just a matter of plugging in redis initializer object, and boom now you have storage in an ACTUAL DB, which can be accessed via multiple socketio nodes and hence more scalable)

kenodek profile image
Dominik Targosz

Really thank you for your exhausting answer