Designing a Scalable WeChat Red Packet System: Database, Caching, and Allocation Algorithms

This article explains how to design and implement a WeChat group red packet feature, covering database schema, non‑cached and cached workflows, concurrency control with Redis locks, and two allocation algorithms—random distribution and double‑average method.

Lobster Programming
Lobster Programming
Lobster Programming
Designing a Scalable WeChat Red Packet System: Database, Caching, and Allocation Algorithms

1. Core Database Schema

Two tables are required:

RedPacket : stores the sender ID, total amount, number of sub‑packets, payment status, expiration time and other metadata.

RedPacketRecord : stores each receiver ID, the associated red‑packet ID, grab timestamp, amount received and payment settlement status.

2. Non‑Cached Processing Flow

2.1 Sending a Red Packet

The client collects the packet parameters (total amount, count, message, etc.) and sends a payment request to the backend. After the payment gateway confirms the transaction, the service creates a RedPacket row, marks it as paid and pushes a notification to the target chat group.

2.2 Grabbing a Red Packet

When a user clicks the packet, the client posts the packet ID to the server. The server executes the following steps atomically (protected by a Redis distributed lock):

Check RedPacketRecord for an existing entry for this user. If found, return the existing result.

Validate the RedPacket record – ensure it is not expired and that remaining_count > 0. If any check fails, return a “packet empty” response.

Insert a new RedPacketRecord row, decrement remaining_count in RedPacket, and commit the transaction.

The lock guarantees that a user can only succeed once per packet and prevents race conditions between concurrent grab attempts.

2.3 Opening (Splitting) a Red Packet

After a successful grab, the client requests the “open” operation. The server again acquires the same lock and performs:

Confirm the existence of a grab record for the user.

Read the current remaining_amount from RedPacket. If zero, return “empty”.

Calculate the user’s share using the selected allocation algorithm (see Section 3).

Update remaining_amount and the corresponding RedPacketRecord with the computed amount.

Unclaimed amounts are refunded to the sender after a 24‑hour scheduled job.

3. Allocation Algorithms

3.1 Random Distribution

For each grab, generate a random value x uniformly in (0, remaining_amount). Assign x to the user, then subtract it from remaining_amount. The expected value decreases as the packet is exhausted, giving early grabbers a statistical advantage.

3.2 Double‑Average (二倍均值) Method

Compute an upper bound for the current grab:

max_amount = (remaining_amount / remaining_count) * 2

Then draw a random number x uniformly in (0, max_amount). This guarantees that no single grab exceeds twice the current average, producing a more equitable distribution while still retaining randomness.

4. Cached (High‑Traffic) Design

To avoid database bottlenecks under heavy load, the packet metadata and remaining counters are cached in Redis.

When a packet is created, its full definition and remaining_count are written to Redis.

The API gateway performs rate‑limiting based on the packet’s total count (e.g., allow 2 × total requests, drop the rest).

During a grab, the service decrements the cached counter, writes a RedPacketRecord entry to a write‑behind queue, and asynchronously persists the record to MySQL. If Redis is unavailable, the request falls back to the database path.

Opening a packet follows the same validation logic, but the amount calculation result is sent to a message queue (MQ) for downstream asynchronous payment processing.

5. Timing of Amount Calculation

Two strategies are possible:

Pre‑calculation : When the packet is sent, split the total amount into count sub‑amounts (using one of the algorithms) and store each sub‑amount in a separate row. This yields O(1) opening latency and strong consistency, at the cost of additional storage.

Real‑time calculation : Compute the amount only when the user opens the packet. This reduces storage overhead and allows dynamic adjustment of the algorithm, but requires the distributed lock and introduces extra CPU work during the open phase.

6. Summary of Design Choices

The workflow is divided into a “grab” phase (traffic filtering) and an “open” phase (amount determination).

The double‑average algorithm is recommended for fair distribution while limiting the maximum per‑grab amount.

Both pre‑calculation and real‑time calculation are viable; the choice depends on performance requirements versus memory consumption.

Redis Lockbackend designcachingAllocation AlgorithmWeChatred packet
Lobster Programming
Written by

Lobster Programming

Sharing insights on technical analysis and exchange, making life better through technology.

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.