[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"academy-blogs-en-1-1-all-go-advanced-multiroom-chat-system-all--*":3,"academy-blog-translations-std3jb4y7l1h15w":78},{"data":4,"page":66,"perPage":66,"totalItems":66,"totalPages":66},[5],{"alt":6,"collectionId":7,"collectionName":8,"content":9,"cover_image":10,"cover_image_path":11,"created":12,"created_by":13,"expand":14,"id":72,"keywords":73,"locale":49,"published_at":74,"scheduled_at":13,"school_blog":70,"short_description":75,"slug":76,"status":68,"title":6,"updated":77,"updated_by":13,"views":71},"EP.113 Building an Advanced Multi-room Chat System with Go and WebSocket","sclblg987654321","school_blog_translations","\u003Cp>In a typical real-time chat system, users often communicate within a single shared room. But as systems grow — like team chats, support channels, game lobbies, or customer groups we must scale the architecture to support multi-room communication with clear room-level separation and control.\u003C\u002Fp>\u003Cp>&nbsp;\u003C\u002Fp>\u003Cp>This episode will guide you through building a scalable multi-room chat system with production-ready features such as:\u003C\u002Fp>\u003Cul>\u003Cli>Room-based message broadcasting\u003C\u002Fli>\u003Cli>Room-level user management\u003C\u002Fli>\u003Cli>Cross-instance communication using Redis Pub\u002FSub\u003C\u002Fli>\u003C\u002Ful>\u003Cp>&nbsp;\u003C\u002Fp>\u003Ch2>🧩 Multi-room Chat System Architecture\u003C\u002Fh2>\u003Cp>&nbsp;\u003C\u002Fp>\u003Cpre>\u003Ccode class=\"language-plaintext\">Client → WebSocket Gateway → Redis Pub\u002FSub → Chat Rooms\n\u003C\u002Fcode>\u003C\u002Fpre>\u003Cp>&nbsp;\u003C\u002Fp>\u003Ch3>Core Components\u003C\u002Fh3>\u003Cul>\u003Cli>Room Manager: Handles room creation, deletion, and member tracking\u003C\u002Fli>\u003Cli>Connection Manager: Tracks user connections per room\u003C\u002Fli>\u003Cli>Redis Pub\u002FSub: Distributes messages across instances for scaling\u003C\u002Fli>\u003C\u002Ful>\u003Cp>&nbsp;\u003C\u002Fp>\u003Ch2>⚙️ Basic Data Structure\u003C\u002Fh2>\u003Cp>&nbsp;\u003C\u002Fp>\u003Cpre>\u003Ccode class=\"language-plaintext language-go\">type Client struct {\n\tID     string\n\tConn   *websocket.Conn\n\tRoomID string\n}\n\ntype Room struct {\n\tID      string\n\tClients map[*Client]bool\n}\n\u003C\u002Fcode>\u003C\u002Fpre>\u003Cp>&nbsp;\u003C\u002Fp>\u003Ch3>Room Manager Setup\u003C\u002Fh3>\u003Cpre>\u003Ccode class=\"language-plaintext language-go\">type RoomManager struct {\n\tRooms map[string]*Room\n\tmu    sync.Mutex\n}\n\nfunc NewRoomManager() *RoomManager {\n\treturn &amp;RoomManager{\n\t\tRooms: make(map[string]*Room),\n\t}\n}\n\u003C\u002Fcode>\u003C\u002Fpre>\u003Cp>&nbsp;\u003C\u002Fp>\u003Ch2>💡 Room &amp; Member Management Functions\u003C\u002Fh2>\u003Cp>&nbsp;\u003C\u002Fp>\u003Cpre>\u003Ccode class=\"language-plaintext language-go\">func (rm *RoomManager) JoinRoom(roomID string, client *Client) {\n\trm.mu.Lock()\n\tdefer rm.mu.Unlock()\n\n\troom, ok := rm.Rooms[roomID]\n\tif !ok {\n\t\troom = &amp;Room{ID: roomID, Clients: make(map[*Client]bool)}\n\t\trm.Rooms[roomID] = room\n\t}\n\n\troom.Clients[client] = true\n\tclient.RoomID = roomID\n}\n\nfunc (rm *RoomManager) LeaveRoom(roomID string, client *Client) {\n\trm.mu.Lock()\n\tdefer rm.mu.Unlock()\n\n\tif room, ok := rm.Rooms[roomID]; ok {\n\t\tdelete(room.Clients, client)\n\t\tif len(room.Clients) == 0 {\n\t\t\tdelete(rm.Rooms, roomID)\n\t\t}\n\t}\n}\n\u003C\u002Fcode>\u003C\u002Fpre>\u003Cp>&nbsp;\u003C\u002Fp>\u003Cp>✅ When a user joins a room, the system checks if the room exists if not, it will automatically create it.\u003C\u002Fp>\u003Cp>&nbsp;\u003C\u002Fp>\u003Ch2>📡 Broadcasting Messages within a Room\u003C\u002Fh2>\u003Cp>&nbsp;\u003C\u002Fp>\u003Cpre>\u003Ccode class=\"language-plaintext language-go\">func (rm *RoomManager) Broadcast(roomID string, msg string) {\n\trm.mu.Lock()\n\tdefer rm.mu.Unlock()\n\n\tif room, ok := rm.Rooms[roomID]; ok {\n\t\tfor c := range room.Clients {\n\t\t\tc.Conn.WriteMessage(websocket.TextMessage, []byte(msg))\n\t\t}\n\t}\n}\n\u003C\u002Fcode>\u003C\u002Fpre>\u003Cp>&nbsp;\u003C\u002Fp>\u003Cp>✅ All users in the same room will receive messages in real-time.\u003C\u002Fp>\u003Cp>&nbsp;\u003C\u002Fp>\u003Ch2>🔄 Scaling with Redis Pub\u002FSub\u003C\u002Fh2>\u003Cp>&nbsp;\u003C\u002Fp>\u003Cp>When you deploy multiple server instances, you'll need to synchronize messages across them. That’s where Redis Pub\u002FSub comes in.\u003C\u002Fp>\u003Cp>&nbsp;\u003C\u002Fp>\u003Cpre>\u003Ccode class=\"language-plaintext language-go\">func subscribeRedis(rm *RoomManager, rdb *redis.Client) {\n\tsub := rdb.Subscribe(context.Background(), \"chat_channel\")\n\tfor msg := range sub.Channel() {\n\t\tvar data struct {\n\t\t\tRoomID  string `json:\"room_id\"`\n\t\t\tMessage string `json:\"message\"`\n\t\t}\n\t\tjson.Unmarshal([]byte(msg.Payload), &amp;data)\n\t\trm.Broadcast(data.RoomID, data.Message)\n\t}\n}\n\nfunc publishMessage(rdb *redis.Client, roomID, msg string) {\n\tdata, _ := json.Marshal(map[string]string{\n\t\t\"room_id\": roomID,\n\t\t\"message\": msg,\n\t})\n\trdb.Publish(context.Background(), \"chat_channel\", data)\n}\n\u003C\u002Fcode>\u003C\u002Fpre>\u003Cp>&nbsp;\u003C\u002Fp>\u003Cp>✅ Now, no matter which server a user is connected to, the message will reach all clients across all machines.\u003C\u002Fp>\u003Cp>&nbsp;\u003C\u002Fp>\u003Ch2>🧠 Advanced Optimization Tips\u003C\u002Fh2>\u003Cp>&nbsp;\u003C\u002Fp>\u003Cfigure class=\"table\">\u003Ctable>\u003Cthead>\u003Ctr>\u003Cth>Category\u003C\u002Fth>\u003Cth>Recommendations\u003C\u002Fth>\u003C\u002Ftr>\u003C\u002Fthead>\u003Ctbody>\u003Ctr>\u003Ctd>Scalability\u003C\u002Ftd>\u003Ctd>Use Redis or NATS for message distribution\u003C\u002Ftd>\u003C\u002Ftr>\u003Ctr>\u003Ctd>Room Types\u003C\u002Ftd>\u003Ctd>Support types like \u003Ccode inline=\"\">global\u003C\u002Fcode>, \u003Ccode inline=\"\">private\u003C\u002Fcode>, \u003Ccode inline=\"\">team\u003C\u002Fcode>\u003C\u002Ftd>\u003C\u002Ftr>\u003Ctr>\u003Ctd>User Management\u003C\u002Ftd>\u003Ctd>Store per-room users in Redis hash\u003C\u002Ftd>\u003C\u002Ftr>\u003Ctr>\u003Ctd>Persistence\u003C\u002Ftd>\u003Ctd>Save chat messages to a database\u003C\u002Ftd>\u003C\u002Ftr>\u003Ctr>\u003Ctd>Monitoring\u003C\u002Ftd>\u003Ctd>Track metrics such as connections per room\u003C\u002Ftd>\u003C\u002Ftr>\u003C\u002Ftbody>\u003C\u002Ftable>\u003C\u002Ffigure>\u003Cp>&nbsp;\u003C\u002Fp>\u003Ch2>🚀 Challenge: Build Your Own!\u003C\u002Fh2>\u003Cp>&nbsp;\u003C\u002Fp>\u003Cp>Try building your own multi-room chat system using Go + WebSocket, and integrate Redis Pub\u002FSub to support distributed message broadcasting.\u003C\u002Fp>\u003Cp>Mastering this architecture means you're ready to build enterprise-grade real-time chat systems!\u003C\u002Fp>\u003Cp>&nbsp;\u003C\u002Fp>\u003Chr>\u003Cp>&nbsp;\u003C\u002Fp>\u003Ch2>🌟 Coming Next: EP.114 Multi-device &amp; Multi-session Management\u003C\u002Fh2>\u003Cp>&nbsp;\u003C\u002Fp>\u003Cp>In the next episode, we’ll explore how to manage multiple devices and sessions per user, design seamless session control, prevent duplication, and support safe, concurrent access across mobile and desktop all over WebSocket! 📱💻\u003C\u002Fp>\u003Cp>&nbsp;\u003C\u002Fp>\u003Cdiv class=\"raw-html-embed\">\u003Cdiv style=\"margin:0 0 6px 0; font-weight:700;\">Read more:\u003C\u002Fdiv>\n\u003Cul style=\"list-style:none; padding:0; margin:0; line-height:1.4;\">\n  \u003Cli style=\"margin:0;\">\u003Ca href=\"\u002Fen\u002Fblogs\u002Fcategories\u002FGolang\" title=\"Golang The Series\">Golang The Series\u003C\u002Fa>\u003C\u002Fli>\n  \u003Cli style=\"margin:0;\">\u003Ca href=\"\u002Fen\u002Fblogs\u002Fcategories\u002FJS2GO\" title=\"JS2GO\">JS2GO\u003C\u002Fa>\u003C\u002Fli>\n  \u003Cli style=\"margin:0;\">\u003Ca href=\"\u002Fen\u002Fblogs\u002Fcategories\u002FTailwind%20CSS\" title=\"Tailwind CSS\">Tailwind CSS\u003C\u002Fa>\u003C\u002Fli>\n\u003C\u002Ful>\u003C\u002Fdiv>\u003Cp>&nbsp;\u003C\u002Fp>\u003Cdiv class=\"raw-html-embed\">\n  \u003Cp style=\"margin:0 0 6px 0;\">\u003Cstrong>Follow Us:\u003C\u002Fstrong>\u003C\u002Fp>\n  \u003Cul style=\"list-style:none; padding:0; margin:0; line-height: 0.4;\">\n    \u003Cli style=\"display:flex; align-items:center; gap:6px; margin:0;\">\n      \n      \u003Csvg width=\"16\" height=\"16\" viewBox=\"0 0 24 24\" fill=\"#1877F2\" aria-hidden=\"true\">\n        \u003Cpath d=\"M22 12.07C22 6.48 17.52 2 11.93 2S2 6.48 2 12.07c0 5 3.66 9.14 8.44 9.93v-7.02H7.9v-2.91h2.54V9.41c0-2.5 1.49-3.88 3.77-3.88 1.09 0 2.24.2 2.24.2v2.46h-1.26c-1.24 0-1.63.77-1.63 1.56v1.87h2.78l-.44 2.91h-2.34V22c4.78-.79 8.44-4.93 8.44-9.93Z\">\u003C\u002Fpath>\n      \u003C\u002Fsvg>\n      \u003Ca href=\"https:\u002F\u002Fwww.facebook.com\u002Fsuperdev.academy.th\" target=\"_blank\" rel=\"nofollow noopener\" title=\"Follow Superdev Academy on Facebook\">Facebook: Superdev Academy\u003C\u002Fa>\n    \u003C\u002Fli>\n\n    \u003Cli style=\"display:flex; align-items:center; gap:6px; margin:0;\">\n      \n      \u003Csvg width=\"16\" height=\"16\" viewBox=\"0 0 24 24\" fill=\"#FF0000\" aria-hidden=\"true\">\n        \u003Cpath d=\"M23.5 6.2a3 3 0 0 0-2.1-2.1C19.5 3.5 12 3.5 12 3.5s-7.5 0-9.4.6A3 3 0 0 0 .5 6.2 31.5 31.5 0 0 0 0 12a31.5 31.5 0 0 0 .5 5.8 3 3 0 0 0 2.1 2.1c1.9.6 9.4.6 9.4.6s7.5 0 9.4-.6a3 3 0 0 0 2.1-2.1A31.5 31.5 0 0 0 24 12a31.5 31.5 0 0 0-.5-5.8ZM9.75 15.02V8.98L15.5 12l-5.75 3.02Z\">\u003C\u002Fpath>\n      \u003C\u002Fsvg>\n      \u003Ca href=\"https:\u002F\u002Fwww.youtube.com\u002F@SuperdevAcademy\" target=\"_blank\" rel=\"nofollow noopener\" title=\"Watch on YouTube\">YouTube: Superdev Academy\u003C\u002Fa>\n    \u003C\u002Fli>\n\n    \u003Cli style=\"display:flex; align-items:center; gap:6px; margin:0;\">\n      \n      \u003Csvg width=\"16\" height=\"16\" viewBox=\"0 0 24 24\" fill=\"#E4405F\" aria-hidden=\"true\">\n        \u003Cpath d=\"M7 2h10a5 5 0 0 1 5 5v10a5 5 0 0 1-5 5H7a5 5 0 0 1-5-5V7a5 5 0 0 1 5-5Zm10 2H7a3 3 0 0 0-3 3v10a3 3 0 0 0 3 3h10a3 3 0 0 0 3-3V7a3 3 0 0 0-3-3Zm-5 3.5A5.5 5.5 0 1 1 6.5 13 5.5 5.5 0 0 1 12 7.5Zm0 2A3.5 3.5 0 1 0 15.5 13 3.5 3.5 0 0 0 12 9.5Zm5.75-2.75a1.25 1.25 0 1 1-1.25 1.25 1.25 1.25 0 0 1 1.25-1.25Z\">\u003C\u002Fpath>\n      \u003C\u002Fsvg>\n      \u003Ca href=\"https:\u002F\u002Fwww.instagram.com\u002Fsuperdevacademy\u002F?hl=en target=\" _blank\"=\"\" rel=\"nofollow noopener\" title=\"See behind-the-scenes on Instagram\">Instagram: Superdev Academy\u003C\u002Fa>\n    \u003C\u002Fli>\n\n    \u003Cli style=\"display:flex; align-items:center; gap:6px; margin:0;\">\n      \n      \u003Csvg width=\"16\" height=\"16\" viewBox=\"0 0 24 24\" fill=\"#000000\" aria-hidden=\"true\">\n        \u003Cpath d=\"M21 8.12a6.86 6.86 0 0 1-4.8-2V16a6 6 0 1 1-6-6 5.9 5.9 0 0 1 1.63.23V8.05a9.08 9.08 0 0 1-1.63-.15V4.5a6.86 6.86 0 0 0 4.8 2.05V6.5a6.86 6.86 0 0 0 4.8 1.62ZM9.2 12.5A3.5 3.5 0 1 0 12.7 16V9.94a6 6 0 0 1-1.63-.27v3.95a3.5 3.5 0 0 1-1.87 3.17 3.5 3.5 0 0 1-4.78-3.23 3.5 3.5 0 0 1 4.78-3.06Z\">\u003C\u002Fpath>\n      \u003C\u002Fsvg>\n      \u003Ca href=\"https:\u002F\u002Fwww.tiktok.com\u002F@superdevacademy\" target=\"_blank\" rel=\"nofollow noopener\" title=\"Watch short tips on TikTok\">TikTok: @superdevacademy\u003C\u002Fa>\n    \u003C\u002Fli>\n\n    \u003Cli style=\"display:flex; align-items:center; gap:6px; margin:0;\">\n      \n      \u003Csvg width=\"16\" height=\"16\" viewBox=\"0 0 24 24\" fill=\"#111827\" aria-hidden=\"true\">\n        \u003Cpath d=\"M12 2a10 10 0 1 0 10 10A10.01 10.01 0 0 0 12 2Zm6.93 6h-3.26a15.6 15.6 0 0 0-1.39-3.62A8.03 8.03 0 0 1 18.93 8ZM12 4c.73.93 1.7 2.74 2.2 4H9.8C10.3 6.74 11.27 4.93 12 4ZM8.72 4.38A15.6 15.6 0 0 0 7.32 8H4.07a8.03 8.03 0 0 1 4.65-3.62ZM4.07 16h3.25a15.6 15.6 0 0 0 1.4 3.62A8.03 8.03 0 0 1 4.07 16ZM12 20c-.73-.93-1.7-2.74-2.2-4h4.4C13.7 17.26 12.73 19.07 12 20Zm3.28-.38A15.6 15.6 0 0 0 16.68 16h3.25a8.03 8.03 0 0 1-4.65 3.62ZM20 14h-3.54a13.8 13.8 0 0 1-.26-4H20a7.98 7.98 0 0 1 0 4Zm-12.2 0H4a7.98 7.98 0 0 1 0-4h3.54a13.8 13.8 0 0 1-.26 4Zm2 .5h4.4a17.8 17.8 0 0 1-.72-4.5c0-1.58.25-3.1.72-4.5H9.8a17.8 17.8 0 0 1 .72 4.5c0 1.58-.25 3.1-.72 4.5Z\">\u003C\u002Fpath>\n      \u003C\u002Fsvg>\n      \u003Ca href=\"https:\u002F\u002Fwww.superdevacademy.com\u002F\" target=\"_blank\" rel=\"noopener\" title=\"Visit the official website of Superdev Academy\">Official Website: Superdev Academy.com\u003C\u002Fa>\n    \u003C\u002Fli>\n  \u003C\u002Ful>\n\u003C\u002Fdiv>\u003Cp>&nbsp;\u003C\u002Fp>","cover_image_ep_i4139690tb.hatSystemwithGo.webp","https:\u002F\u002Ftwsme-r2.tumwebsme.com\u002Fsclblg987654321\u002Fh6wvekawibs30q7\u002Fcover_image_ep_i4139690tb.hatSystemwithGo.webp","2026-03-04 08:45:12.781Z","",{"keywords":15,"locale":43,"school_blog":53},[16,23,28,33,38],{"collectionId":17,"collectionName":18,"created":19,"created_by":13,"id":20,"name":21,"updated":22,"updated_by":13},"sclkey987654321","school_keywords","2026-03-04 08:44:51.471Z","hlato0hav8vo8wm","Golang The Series","2026-04-10 16:12:50.850Z",{"collectionId":17,"collectionName":18,"created":24,"created_by":13,"id":25,"name":26,"updated":27,"updated_by":13},"2026-03-04 08:45:12.082Z","d1gcnwwosqk2zn0","redis pubsub","2026-04-10 16:12:55.686Z",{"collectionId":17,"collectionName":18,"created":29,"created_by":13,"id":30,"name":31,"updated":32,"updated_by":13},"2026-03-04 08:45:12.418Z","vbx3b3qn50sn0tr","Multi-room Chat","2026-04-10 16:12:55.814Z",{"collectionId":17,"collectionName":18,"created":34,"created_by":13,"id":35,"name":36,"updated":37,"updated_by":13},"2026-03-04 08:34:00.920Z","ecac9y661or1xka","WebSocket","2026-04-10 16:08:05.227Z",{"collectionId":17,"collectionName":18,"created":39,"created_by":13,"id":40,"name":41,"updated":42,"updated_by":13},"2026-03-04 08:20:11.547Z","ey3puyme01a9bsw","Go","2026-04-10 16:07:25.893Z",{"code":44,"collectionId":45,"collectionName":46,"created":47,"flag":48,"id":49,"is_default":50,"label":51,"updated":52},"en","pbc_1989393366","locales","2026-01-22 11:00:02.726Z","twemoji:flag-united-states","qv9c1llfov2d88z",false,"English","2026-04-10 15:42:46.825Z",{"category":54,"collectionId":55,"collectionName":56,"expand":57,"id":70,"views":71},"wqxt7ag2gn7xcmk","pbc_2105096300","school_blogs",{"category":58},{"blogIds":59,"collectionId":60,"collectionName":61,"created":62,"created_by":13,"id":54,"image":63,"image_alt":13,"image_path":64,"label":65,"name":21,"priority":66,"publish_at":67,"scheduled_at":13,"status":68,"updated":69,"updated_by":13},[],"sclcatblg987654321","school_category_blogs","2026-03-04 08:33:53.210Z","59ty92ns80w_15oc1implw.png","https:\u002F\u002Ftwsme-r2.tumwebsme.com\u002Fsclcatblg987654321\u002Fwqxt7ag2gn7xcmk\u002F59ty92ns80w_15oc1implw.png",{"en":21,"th":21},1,"2026-03-16 04:39:38.440Z","published","2026-04-25 02:32:15.470Z","std3jb4y7l1h15w",205,"h6wvekawibs30q7",[20,25,30,35,40],"2025-12-02 03:38:44.862Z","Learn how to build a scalable real-time chat system that supports multiple rooms, with message broadcasting and Redis Pub\u002FSub integration to handle multi-instance production environments.","go-advanced-multiroom-chat-system","2026-04-25 02:47:50.655Z",{"en":76}]