View : 0

12/04/2026 18:17pm

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