View : 227
06/05/2026 08:38am

EP.37 Creating a Chat Room Management System with WebSocket and GraphQL
#Group Chat
#GraphQL API
#WebSocket API
#Chat Room Management
#Real-Time Chat
#Golang
#Go
#GraphQL
#WebSocket
#Chat Room
Why Have a Chat Room System?
A chat room system allows users to organize discussions into smaller groups, where only relevant users are present in each room. This is suitable for:
- Group Chats: Members can join or leave rooms as needed.
- Topic-Based Chat Rooms: For example, discussion rooms for teams within a company.
- Customer Support Chats: Agents can enter rooms to address customer inquiries.
Structure of the Chat Room Management System
- WebSocket Server: Manages user connections and sends messages to the relevant rooms.
- GraphQL API: Supports commands for creating rooms, joining rooms, and sending/receiving messages.
- Database (PostgreSQL / MongoDB): Used to store room and message data.
- GraphQL Subscription: Sends messages to members in the room in real-time.
Install Necessary Libraries
go get github.com/99designs/gqlgen
go get github.com/gorilla/websocket
go get github.com/jmoiron/sqlxDatabase Setup for the Chat Room System
File: schema.sql
CREATE TABLE chat_rooms (
id SERIAL PRIMARY KEY,
name TEXT NOT NULL UNIQUE
);
CREATE TABLE messages (
id SERIAL PRIMARY KEY,
room_id INTEGER REFERENCES chat_rooms(id),
content TEXT NOT NULL,
sender TEXT NOT NULL,
timestamp TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);Creating GraphQL Schema for the Chat Room System
File: schema.graphql
type Query {
rooms: [ChatRoom!]!
messages(roomID: ID!): [Message!]!
}
type Mutation {
createRoom(name: String!): ChatRoom!
joinRoom(roomID: ID!): String!
sendMessage(roomID: ID!, content: String!, sender: String!): Message!
}
type Subscription {
messageAdded(roomID: ID!): Message!
}
type ChatRoom {
id: ID!
name: String!
}
type Message {
id: ID!
roomID: ID!
content: String!
sender: String!
timestamp: String!
}Creating Resolvers for the Chat Room System
File: resolver.go
package main
import (
"context"
"database/sql"
"fmt"
"sync"
"time"
_ "github.com/lib/pq"
)
type ChatRoom struct {
ID int `json:"id"`
Name string `json:"name"`
}
type Message struct {
ID int `json:"id"`
RoomID int `json:"roomID"`
Content string `json:"content"`
Sender string `json:"sender"`
Timestamp time.Time `json:"timestamp"`
}
type Resolver struct {
mu sync.Mutex
db *sql.DB
subscribers map[int]map[string]chan Message
}
func NewResolver(db *sql.DB) *Resolver {
return &Resolver{
db: db,
subscribers: make(map[int]map[string]chan Message),
}
}
func (r *Resolver) Query_rooms(ctx context.Context) ([]ChatRoom, error) {
rows, err := r.db.Query("SELECT id, name FROM chat_rooms")
if err != nil {
return nil, err
}
defer rows.Close()
var rooms []ChatRoom
for rows.Next() {
var room ChatRoom
if err := rows.Scan(&room.ID, &room.Name); err != nil {
return nil, err
}
rooms = append(rooms, room)
}
return rooms, nil
}
func (r *Resolver) Mutation_createRoom(ctx context.Context, name string) (ChatRoom, error) {
var room ChatRoom
err := r.db.QueryRow("INSERT INTO chat_rooms (name) VALUES ($1) RETURNING id, name", name).
Scan(&room.ID, &room.Name)
return room, err
}
func (r *Resolver) Mutation_sendMessage(ctx context.Context, roomID int, content string, sender string) (Message, error) {
var message Message
err := r.db.QueryRow("INSERT INTO messages (room_id, content, sender) VALUES ($1, $2, $3) RETURNING id, room_id, content, sender, timestamp", roomID, content, sender).
Scan(&message.ID, &message.RoomID, &message.Content, &message.Sender, &message.Timestamp)
r.mu.Lock()
for _, ch := range r.subscribers[roomID] {
ch <- message
}
r.mu.Unlock()
return message, err
}Challenge!
Try adding an admin feature to the chat room system that allows administrators to set user permissions, such as deleting messages or restricting access.
Next EP
In EP.38, we will add Push Notification support to the WebSocket Chat! 🚀