Inside WeChat’s Group Chat: Architecture, High‑Concurrency Design, and Red‑Packet Algorithm

This article dissects WeChat's group chat system, covering its functional and non‑functional requirements, high‑level architecture, face‑to‑face group creation, message transmission, storage design, and the real‑time red‑packet allocation algorithm implemented in Go.

Java Backend Technology
Java Backend Technology
Java Backend Technology
Inside WeChat’s Group Chat: Architecture, High‑Concurrency Design, and Red‑Packet Algorithm

1. Introduction

While chatting in a WeChat group, a congratulatory message "恭喜发财,大吉大利" appears, prompting curiosity about how the group chat and red‑packet features are designed.

2. System Requirements

2.1 Functional Requirements

创建群聊 :Users can create a new chat group and invite friends or strangers.

群组管理 :Group owners and admins manage members, set rules and permissions.

消息发送和接收 :Support sending text, images, audio, video, etc., to all group members.

实时通信 :Messages must be delivered quickly for real‑time interaction.

抢红包 :Users can send any number of red packets with random amounts, and members can claim them.

2.2 Non‑functional Requirements

高并发 :Support massive simultaneous group creation and usage for billions of daily users.

高性能 :Fast message delivery and instant response are essential.

海量存储 :Scalable storage for massive text, image, audio, and video data.

3. High‑Level Design

3.1 Core Components

客户端 :Receives group chat messages on mobile or PC and forwards them to the backend.

Websocket传输协议 :Low‑overhead, high‑real‑time bidirectional communication.

长连接集群 :Handles WebSocket long connections and forwards messages to application servers.

消息处理服务器集群 :Processes messages, stores data, and interacts with databases.

消息推送服务器集群 :Routes messages to the correct group members.

数据库服务器集群 :Stores user text, image thumbnails, audio/video metadata.

分布式文件存储集群 :Stores user‑uploaded images, audio, and video files.

3.2 Business Overview

Group Creation

唯一ID分配 :Generate a unique group ID using a distributed ID generator (e.g., Snowflake) or MySQL auto‑increment.

群组信息存储 :Persist group ID, name, creator ID, member count, etc., in the group table.

成员关联 :Add the creator as the first member and admin.

消息历史记录 :Link group ID with user messages so new members can view past chats.

In addition to normal friend‑based groups, WeChat supports face‑to‑face group creation.

We will later explore the detailed design of face‑to‑face creation, message sending/receiving, and the red‑packet feature.

4. Face‑to‑Face Group Creation

4.1 Database Table Design

User table – stores user ID, nickname, avatar, etc.

Group table – stores group ID, name, creator ID, member count.

GroupMember table – maps users to groups.

RandomCode table – stores the 4‑digit random code and associated group ID.

4.2 Core Interaction Flow

User A creates a face‑to‑face group, generates a random 4‑digit code, and stores HashMap {code → [UserA]} in Redis with a 3‑minute TTL. Nearby users (within ~50 m) input the same code, see the pending group, and join.

When the first user clicks “Enter Group”, the system saves the random code in RandomCode, links it to the newly created group, and updates member counts. User and group information are persisted in Group and GroupMember tables.

5. Message Sending and Receiving

5.1 Interaction Flow

User A sends a message with optional media.

The client uploads the content and media to the backend.

The backend stores the message in the Message table and media files in the distributed file storage, recording MediaID, thumbnails, etc.

The backend broadcasts the message to all group members; clients render it according to its type.

When a user clicks a media thumbnail, the client fetches the file via MediaID from object storage and displays it.

5.2 Message Storage and Presentation

Message table – stores MessageID, type (text, image, video, audio), content, sender ID, group ID, timestamp.

Media table – stores MediaID, file path, uploader ID, upload time.

MessageState table – tracks read/unread status per user; unread counts are cached in Redis to avoid full table scans.

When unread count exceeds 99, the system caps the displayed count at “99+” to improve performance.

6. Red‑Packet Feature

6.1 Database Design

redpack table – id (PK), totalAmount, surplusAmount, total, surplusTotal, userId (sender).

redpack_record table – id (PK), redpackId (FK), userId, amount (claimed).

6.2 Real‑time Handling

User sets total amount and count; a record is inserted into redpack.

Redis stores the red‑packet ID and remaining count for fast atomic decrement.

Push notification is sent to all group members.

When a member claims, the backend validates eligibility, atomically decrements the count, and records the claim.

Transfer to the user’s wallet is performed asynchronously.

6.3 Allocation Algorithm

The system uses the “two‑times‑average” method: for each claim, a random amount is generated between 0.01 and twice the current average (remaining amount ÷ remaining count). The last claim receives the remaining balance.

故可能出现很大的红包差额,但这更刺激不是吗🐶

Go implementation:

import (
    "fmt"
    "math"
    "math/rand"
    "strconv"
)

type RedPack struct {
    SurplusAmount float64 // 剩余金额
    SurplusTotal  int    // 红包剩余个数
}

// 取两位小数
func remainTwoDecimal(num float64) float64 {
    numStr := strconv.FormatFloat(num, 'f', 2, 64)
    num, _ = strconv.ParseFloat(numStr, 64)
    return num
}

// 获取随机金额的红包
func getRandomRedPack(rp *RedPack) float64 {
    if rp.SurplusTotal <= 0 {
        return 0
    }
    if rp.SurplusTotal == 1 {
        return remainTwoDecimal(rp.SurplusAmount + 0.01)
    }
    avgAmount := math.Floor(100*(rp.SurplusAmount/float64(rp.SurplusTotal))) / 100
    avgAmount = remainTwoDecimal(avgAmount)
    rand.Seed(time.Now().UnixNano())
    var max float64
    if avgAmount > 0 {
        max = 2*avgAmount - 0.01
    } else {
        max = 0
    }
    money := remainTwoDecimal(rand.Float64()*max + 0.01)
    rp.SurplusTotal -= 1
    rp.SurplusAmount = remainTwoDecimal(rp.SurplusAmount + 0.01 - money)
    return money
}

func main() {
    rp := &RedPack{SurplusAmount: 0.06, SurplusTotal: 5}
    rp.SurplusAmount -= 0.01 * float64(rp.SurplusTotal)
    total := rp.SurplusTotal
    for i := 0; i < total; i++ {
        fmt.Println(getRandomRedPack(rp))
    }
}
0.01、0.01、0.01、0.01、0.02

7. Conclusion

WeChat's group chat, message handling, and red‑packet features involve complex interaction logic, carefully designed components, and optimized database schemas, enabling billions of users to communicate smoothly and enjoy engaging social experiences.

Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

GoSystem Designhigh concurrencyWeChatred packetgroup chat
Java Backend Technology
Written by

Java Backend Technology

Focus on Java-related technologies: SSM, Spring ecosystem, microservices, MySQL, MyCat, clustering, distributed systems, middleware, Linux, networking, multithreading. Occasionally cover DevOps tools like Jenkins, Nexus, Docker, and ELK. Also share technical insights from time to time, committed to Java full-stack development!

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.