View : 206

08/05/2026 06:52am

EP.111 Message Ordering & Event Sequence Management for WebSocket Systems

EP.111 Message Ordering & Event Sequence Management for WebSocket Systems

#WebSocket

#Message Ordering

#Event Sequence

#Golang WebSocket

#Go

In WebSocket systems with thousands of concurrent users, one of the most common problems is out-of-order messages. 😩

 

For example, User A sends 3 messages in sequence, but User B receives them in this order: 2 → 1 → 3.

 

Common causes include:

  • Simultaneous data sending from multiple goroutines
  • Reconnects where events aren't synced in time
  • Cross-instance broadcasts without proper ordering logic

 

This episode will walk you through message ordering techniques and event sequence handling to ensure your WebSocket system is 100% accurate and production-ready. 🚀

 

🧩 1. Why Message Ordering Matters

 

In real-time systems such as:

  • Chat applications
  • Online games
  • Collaborative editing tools

 

Message order directly impacts data integrity.

ExamplePotential Impact
Chat messages swappedMisunderstandings between users
Game event delaysLag or incorrect in-game behavior
Out-of-order data updatesIncorrect or duplicate information

 

⚙️ 2. Assigning Sequence Numbers to All Messages

 

Each WebSocket message should include a sequence_id (int) to indicate its order per user.

 

Example JSON structure:

{
  "user_id": "u123",
  "sequence_id": 42,
  "message": "Hello world",
  "timestamp": "2025-11-23T21:15:00Z"
}

 

Go struct:

type Message struct {
	UserID     string `json:"user_id"`
	SequenceID int    `json:"sequence_id"`
	Content    string `json:"message"`
	Timestamp  string `json:"timestamp"`
}

 

✅ Increment sequence_id by 1 for each new message and persist it in the database.

 

🔀 3. Checking Sequence Before Broadcast

 

In systems with thousands of users and multiple concurrent broadcasts, messages may arrive out of order. Use a queue per chat room and single goroutine to maintain sequence.

 

Example code:

func broadcastMessages(roomID string, msgChan <-chan Message) {
	lastSeq := 0
	for msg := range msgChan {
		if msg.SequenceID == lastSeq+1 {
			for client := range rooms[roomID] {
				client.Conn.WriteJSON(msg)
			}
			lastSeq = msg.SequenceID
		} else {
			log.Printf("Skipped or delayed message: %v", msg.SequenceID)
		}
	}
}

 

✅ A single goroutine per room ensures order and reduces race conditions.

 

🧠 4. Syncing Events Across Instances Using Redis Pub/Sub

 

In multi-instance systems (e.g., multiple Pods in Kubernetes), use Redis Pub/Sub to sync messages across nodes.

 

Example code:

func handleRedisMessages() {
	sub := redisClient.Subscribe(ctx, "event_channel")
	for msg := range sub.Channel() {
		var event Message
		json.Unmarshal([]byte(msg.Payload), &event)
		eventQueue <- event
	}
}

 

✅ Push events into a shared eventQueue and sort them by sequence_id before broadcasting.

 

📈 5. Handling Out-of-Order Recovery

 

If a client receives message 45 but misses 44, the system should provide resync or message recovery.

 

Example idea:

func handleResync(conn *websocket.Conn, lastReceived int) {
	missing := getMessagesSince(lastReceived)
	for _, m := range missing {
		conn.WriteJSON(m)
	}
}

 

✅ Only the missing messages are sent during recovery.

 

🔒 6. Best Practices Summary

 

CategoryBest Practice
SequenceAssign sequence_id to every message
BroadcastUse a queue + single goroutine per room
Multi-instanceSync via Redis Pub/Sub
ReconnectSupport message recovery
StorageStore timestamp + sequence_id for replay

 

🚀 Challenge for You!

 

Try building a real-time chat system where every message includes a sequence_id. Let your client verify if messages are in the correct order. 🔢

 

You’ll quickly realize that message ordering is the heart of production-grade real-time systems! 💬

 


 

🌟 Next EP: EP.112 Building Real-Time Notification Systems

 

In the next episode, we’ll dive into real-time notifications, showing how to deliver push updates over WebSocket when critical events occur. 🔔