Massive Group Chat Technical Solution: Breaking the Group Member Count Limit

Deep dive into JuggleIM's group design: how it supports 100,000-person super groups

Introduction

In IM systems, group chat is one of the most technically demanding scenarios.

A two-person private chat has simple, direct message-distribution logic. But when the group size grows to 1,000, 10,000, or even 100,000 members, the complexity grows geometrically:

  • Sending a single message means "replicating" it to every group member
  • Querying and maintaining the group member list becomes a performance bottleneck
  • Message-ordering consistency is challenged
  • Features like read receipts become much harder to implement

Today, let's dive into JuggleIM's group design and see how it solves these challenges at the architectural level, supporting massive groups and even larger.

1. The Essential Difference Between Group Chat and Private Chat

Before exploring the technical solution, we need to understand how group chat and private chat differ in essence.

Difference 1: Message Fan-out

Private chat is one-to-one: sending a message only needs to deliver it to one person.

Group chat is one-to-many: sending a message means delivering it to N people, where N can be dozens, hundreds, or even tens of thousands.

This is the so-called message fan-out problem. The larger the fan-out factor, the more system pressure.

Difference 2: Member Dynamics

The two sides of a private chat are fixed.

The members of a group chat are dynamic — people can join or leave at any time. This raises a question: when a message is sent, who should receive it? The members at send time, or the members at receive time?

Difference 3: State Maintenance

Private chat mainly maintains conversation state and message state.

Group chat additionally needs to maintain:

  • Group basic info (name, avatar, announcement)
  • Member list and roles (owner, admin, regular member)
  • Member permissions (mute, blacklist)
  • Group settings (whole-group mute, join verification)

The more complex the state, the harder it is to maintain consistency.

2. JuggleIM's Group Architecture

JuggleIM's group functionality is handled by the Group service, which works with the Message, Conversation, and other services to deliver the complete group chat feature set.

Core Module Division

The Group service internally contains over a dozen Actors, each with a specific responsibility:

Group Management

  • DissolveGroupActor: dissolves a group
  • UpdGroupInfoActor: updates group info

Member Management

  • AddMemberActor: adds a group member
  • DelMemberActor: removes a group member
  • QryGroupMembersActor: queries the group member list
  • CheckGroupMemberActor: verifies group membership

Permission Management

  • GroupMuteActor: group-mute settings
  • GroupMemberMuteActor: per-member mute
  • GroupMemberAllowActor: member whitelist

Message Processing

  • GroupMsgActor: group message processing
  • ImportGroupHisMsgActor: imports history messages

Data Model Design

Group Basic Info Table

Stores the group's basic attributes, one record per group:

Field Description
group_id Group ID
group_name Group name
group_portrait Group avatar
is_mute Whether the whole group is muted
created_time Creation time
updated_time Update time
app_key App identifier

Index design: (app_key, group_id) unique index.

Group Member Table

Stores group-member relationships, one record per member:

Field Description
group_id Group ID
member_id Member ID
member_type Member type (owner / admin / regular)
is_mute Whether muted
is_allow Whether on the whitelist
mute_end_at Mute end time
created_time Join time

Index design:

  • (app_key, group_id, member_id) unique index
  • (app_key, member_id, group_id) auxiliary index for querying which groups a user has joined

This design makes both "list the groups a user has joined" and "list the members of a group" efficient.

3. The Complete Pipeline of Sending a Group Message

What happens inside the system when a user sends a message in a group?

Step 1: Message Receipt and Validation

The message sent by the user reaches the ConnectManager, which routes it to GroupMsgActor.

Validation 1: Member Validation

  • Verify that the sender is still a group member
  • If already kicked out, reject the send

Validation 2: Mute Validation

  • Check whether the whole group is muted
  • If so, check whether the sender is on the whitelist
  • Check whether the sender is individually muted

If validation fails, the corresponding error code is returned, and the client can prompt the user.

Step 2: Message Storage

Once validation passes, the message is persisted:

Store in the history message table

  • Write to the g_hismsgs table (group-chat history messages)
  • Generate a globally unique message ID
  • Record send time, message type, and content

Record a group member snapshot

  • Associate the message with the group member list at send time
  • This ensures there is a reliable record for "who should have received this message"

Step 3: Conversation Update

Update the sender's conversation list:

  • Update the latest message
  • Update the conversation time
  • Ensure the group conversation appears at the top of the list

Step 4: Message Distribution

This is the most critical step for group messages — delivering the message to all group members.

Get the member list

  • Query the member table for all current group members

Filter online members

  • Query the connection manager to see which members are online
  • Distinguish online from offline members

Online push

  • Construct a push message for each online member
  • Deliver directly via the long connection

Offline handling

  • Write to the inbox, waiting for the user to come online and pull
  • Trigger a push notification

Step 5: Return Confirmation

Return a success ACK to the sender, containing:

  • The server-generated message ID
  • The server timestamp

4. Performance Optimizations for Large-Group Scenarios

The above flow is fine for small groups, but when the group size reaches tens of thousands, every step can become a bottleneck. JuggleIM has done many optimizations.

Optimization 1: Paged Member Query

For a 10,000-person group, returning the entire member list at once puts a lot of pressure on the database and network.

JuggleIM uses paged queries:

  • The client passes paging parameters when requesting
  • The server returns members page by page
  • Supports filtering by member type (e.g. admins only)

This way, the client can load on demand, improving the experience while reducing server pressure.

Optimization 2: Batch Writes

Group message distribution involves a lot of database writes (one record per member's inbox).

JuggleIM uses a batch write strategy:

  • Combine multiple records into a single SQL execution
  • Reduce database connection overhead
  • Significantly improve write throughput

Optimization 3: Async Distribution

For large groups, synchronously waiting for all members to be delivered causes send timeouts.

JuggleIM uses async distribution:

  • The ACK is returned immediately after the message is stored
  • Distribution happens asynchronously
  • Failed deliveries are guaranteed via a retry mechanism

This way, the sender's perceived latency is very low, and the user experience is good.

Optimization 4: Push Aggregation

Group messages can trigger many push notifications. If a group has multiple messages in a short time, users would get a "spam flood" of notifications.

JuggleIM supports push aggregation:

  • Multiple messages within a certain time window are merged into one push
  • The push text shows "N new messages in the group"
  • Reduces disturbance to the user

Optimization 5: Group Member Caching

Frequently querying the database for the group member list is expensive.

JuggleIM uses caching to speed it up:

  • Member lists of hot groups are cached in memory
  • The cache is updated on member changes
  • Periodically refreshed to ensure consistency

5. Group Snapshot Mechanism

Group members are dynamic, which raises a question: who should historical messages be shown to?

Consider this scenario:

  • Xiao Ming sends a message in the group
  • 1 minute later, Xiao Hong joins the group
  • Should Xiao Hong see the message Xiao Ming just sent?

Different IM products have different strategies. JuggleIM uses the group snapshot mechanism to record the group member state at the time a message is sent.

Purpose of Snapshots

The snapshot records the group member list at the instant a message is sent. This enables:

  • Precisely knowing who should have received the message
  • Accurate "denominator" for read-receipt calculation
  • A basis for message audit and traceability

Snapshot Storage

JuggleIM uses the grpsnapshots table to store group snapshots:

Field Description
group_id Group ID
created_time Snapshot creation time
snapshot Snapshot content (member list)

The snapshot content is stored as binary data and compressed to take up less space.

When Snapshots Are Generated

Not every message needs to generate a snapshot (that would be too storage-expensive). JuggleIM's strategy:

  • The message record references the snapshot's timestamp
  • When querying which members correspond to a message, find the nearest snapshot
  • Important messages (e.g. with read-receipt requirements) can trigger a new snapshot

6. Group Read-Receipt Design

In enterprise scenarios, group read receipts are a must-have — senders need to know who has read the message.

Design Challenges

Read receipts in large groups are challenging:

  • A 10,000-person group, with one read record per person, creates huge data volume
  • Real-time querying of the read count must be efficient
  • Detailed read-status queries (who read, who didn't) need to be supported

JuggleIM's Solution

Read-record table design

readinfos table:

  • msg_id: message ID
  • group_id: group ID
  • member_id: member ID
  • created_time: read time

Index design supports:

  • Query the list of members who have read a given message
  • Query the list of messages a given member has read

Read-count optimization

The history message table has a read_count field, which caches the current read count.

  • The count is incremented on each read report
  • Queries return this value directly, no need for real-time aggregation

Batch reporting

Instead of reporting each read individually, the client reports in batches:

  • Reports all messages read up to a given time point
  • The server processes them in batches, reducing request count

7. Group Message Ordering Consistency

In a distributed system, ensuring message ordering is a challenge.

Problem Scenario

Consider this scenario:

  • A and B send messages in the group almost simultaneously
  • A's message reaches the server first, getting timestamp T1
  • B's message reaches the server later, getting timestamp T2 (T2 > T1)
  • But during network transmission, B's message reaches C's client first

C sees the order B→A, but the actual order should be A→B.

JuggleIM's Guarantees

JuggleIM ensures ordering through these mechanisms:

Server-side sorting

  • Messages are sorted by server timestamp
  • All clients sort messages by timestamp when pulling

Client-side local sorting

  • The client re-sorts messages by timestamp after receiving them
  • Even if the arrival order is wrong, the displayed order is correct

Message sequence number

  • In addition to timestamps, messages have an auto-incrementing sequence number
  • Sequence numbers within a group strictly increase
  • Clients can detect missing messages

8. Other Advanced Group Features

In addition to core messaging, JuggleIM's groups support many advanced capabilities.

Group Management

  • Group info update: modify group name, avatar, announcement
  • Group dissolution: the owner can dissolve the group, cleaning up related data
  • Member settings: each member can set a group nickname, do-not-disturb

Permission Control

  • Member roles: owner > admin > regular member
  • Mute functions: whole-group mute, individual mute, timed mute
  • Whitelist: when muted, allow specific members to speak

Member Extended Info

The groupmemberexts table can store extended attributes for members:

  • Group nickname
  • Join method (invite / scan / search)
  • Custom tags

9. Extreme Scenario: 100,000-Person Groups

When a group reaches 100,000 members or more, additional considerations are required:

Adjusted Message Distribution Strategy

  • Consider using message queues for async processing
  • Sharded distribution, parallel processing across multiple nodes
  • Differentiated delivery, VIP users first

Storage Optimization

  • Consider sharding the member table (by group_id hash)
  • Consider hot/cold separation for history messages
  • Consider incremental storage for snapshots instead of full snapshots

Business-Level Constraints

  • Limit message-send frequency
  • Simplify message types (e.g. text-only)
  • Read receipts may need to be downgraded or disabled

Super-large group scenarios are relatively special and usually require custom optimization based on specific business needs.

Project URL: https://github.com/juggleim/im-server