View : 232

06/05/2026 08:38am

EP.88 Building a Multi-room Chat System with WebSocket

EP.88 Building a Multi-room Chat System with WebSocket

#WebSocket

#Golang

#Go

#chat system

A great WebSocket Chat system isnโ€™t just about allowing users to connect โ€” it should support a multi-room chat architecture, where users can join different rooms, send messages within groups, and manage room members efficiently.

 

In this article, weโ€™ll walk you through how to build a scalable multi-room chat system using Golang + WebSocket, along with real-time member management and secure communication techniques.

 

๐Ÿ”ง Core Structure of a Multi-room Chat System

 

The architecture consists of three main components:

type Client struct {
    ID     string
    Conn   *websocket.Conn
    RoomID string
    Send   chan []byte
}

type Room struct {
    ID        string
    Clients   map[string]*Client
    Broadcast chan []byte
}

type Hub struct {
    Rooms      map[string]*Room
    Register   chan *Client
    Unregister chan *Client
}
  • Client: Represents each connected user with its connection and associated room
  • Room: Holds users within the same chat room and provides a broadcast channel
  • Hub: A central manager that handles room creation, user registration, and room clean-up

 

๐Ÿงฉ Registering and Unregistering Clients

 

func (h *Hub) Run() {
    for {
        select {
        case client := <-h.Register:
            room, ok := h.Rooms[client.RoomID]
            if !ok {
                room = &Room{
                    ID:        client.RoomID,
                    Clients:   make(map[string]*Client),
                    Broadcast: make(chan []byte),
                }
                h.Rooms[client.RoomID] = room
                go room.Run()
            }
            room.Clients[client.ID] = client

        case client := <-h.Unregister:
            if room, ok := h.Rooms[client.RoomID]; ok {
                delete(room.Clients, client.ID)
                close(client.Send)
                if len(room.Clients) == 0 {
                    delete(h.Rooms, room.ID)
                }
            }
        }
    }
}
  • Register: Adds a client to a room, automatically creates the room if it doesnโ€™t exist
  • Unregister: Removes a client from the room, and deletes the room if empty

 

๐Ÿ“ข Broadcasting Messages Within Rooms

 

func (r *Room) Run() {
    for {
        select {
        case message := <-r.Broadcast:
            for _, client := range r.Clients {
                select {
                case client.Send <- message:
                default:
                    close(client.Send)
                    delete(r.Clients, client.ID)
                }
            }
        }
    }
}

Messages sent to the Broadcast channel are immediately forwarded to all clients in the room. If a client becomes unresponsive, its channel is closed to prevent blocking the room.

 

๐Ÿ”„ Sending and Receiving Messages (Client Side)

 

func (c *Client) ReadPump(h *Hub) {
    defer func() {
        h.Unregister <- c
        c.Conn.Close()
    }()
    for {
        _, msg, err := c.Conn.ReadMessage()
        if err != nil {
            break
        }
        if room, ok := h.Rooms[c.RoomID]; ok {
            room.Broadcast <- msg
        }
    }
}

func (c *Client) WritePump() {
    for msg := range c.Send {
        c.Conn.WriteMessage(websocket.TextMessage, msg)
    }
}
  • ReadPump: Reads messages from the client and sends them to the appropriate room
  • WritePump: Sends messages from the room to the client in real time

 

๐Ÿ‘ฅ Managing Room Members

 

Want to display a list of users in a room? Hereโ€™s a simple function:

func (r *Room) ListMembers() []string {
    members := []string{}
    for id := range r.Clients {
        members = append(members, id)
    }
    return members
}

You can also expose endpoints like /join-room, /leave-room, or /members to control and manage rooms from the frontend.

 

๐Ÿง  Production Considerations

 

Here are tips to make your chat system production-ready:

โœ… Use Redis Pub/Sub to share messages across server instances
โœ… Enforce connection limits per room to prevent abuse
โœ… Enable Gzip compression to reduce WebSocket message sizes

 


 

๐Ÿš€ Challenge: Build It Yourself!

 

Try building your own multi-room chat server and expand with features like:

  • Private Rooms
  • Room Admin Roles
  • Join/Leave Notifications

 

๐Ÿ”œ Next Episode

 

EP.89: Load Testing Your WebSocket Server Like a Pro

In the next article, weโ€™ll explore how to benchmark your WebSocket system and ensure it can handle thousands of concurrent connections under real-world load.

 

Read more

๐Ÿ”ต Facebook: Superdev Academy

๐Ÿ”ด YouTube: Superdev Academy

๐Ÿ“ธ Instagram: Superdev Academy

๐ŸŽฌ TikTok: https://www.tiktok.com/@superdevacademy?lang=th-TH

๐ŸŒ Website: https://www.superdevacademy.com/en