How WeChat Resets 1 Billion Step Counts at Midnight Without Crashing

WeChat avoids server crashes during midnight step-count resets for 1 billion users by using logical time-based versioning instead of physical updates, a custom PaxosStore for atomic increments, delayed double-write buffers for clock skew, Redis ZSet sharding for rankings, and asynchronous cold-data archival during low-traffic hours.

ITPUB
ITPUB
ITPUB
How WeChat Resets 1 Billion Step Counts at Midnight Without Crashing

Why a Naive MySQL UPDATE Fails

At midnight, nearly 1 billion active WeChat users simultaneously reset their step counts, trigger yesterday's settlement, fetch group leaderboards, and generate billions of "like" write conflicts. This is a coordinated, clock-driven DDoS with no user-behavior buffer.

A typical reflex is a cron job running UPDATE on a 1-billion-row table. That would cause massive row/table lock contention, saturate IOPS, and deadlock the database.

WeChat's Storage Layering

MySQL as Final Immutable Archive

WeChat retains MySQL but places it at the end of the storage chain. All burst traffic (likes, high-frequency step uploads, leaderboard reads) is absorbed 100% in the memory cache layer and custom distributed middleware. Only aggregated, peak-shaved, cleaned "cold ledgers" reach MySQL via message queues.

Aggressive Sharding by UIN

WeChat runs hundreds of thousands of MySQL instances. Users are hashed by UIN into tiny shards — each table handles ~10,000 users. At midnight, the global peak is spread across countless physical servers; a single instance only sees its 10,000 users writing one history record each.

Core Storage: PaxosStore

WeChat's core businesses (Moments, third-party login, WeChat Run) run on PaxosStore , a home-grown, multi-replica, strongly consistent distributed KV/Table store based on the Paxos protocol.

Peak absorption: PaxosStore uses memory + WAL (write-ahead log). Step uploads perform atomic increments in memory and persist logs, delivering throughput orders of magnitude higher than traditional RDBMS.

UIN routing: Step data is numeric. PaxosStore keys on UIN (uint32_t) for O(1) reads/writes, forming an unshakeable "flood wall" at the front end.

Multi-DC Autonomous Loops

WeChat adopts "user-affinity autonomy": writes go to the user's home data center (e.g., Shenzhen for southern users, Shanghai for northern). Leaderboard settlement runs locally in each DC's cache cluster, then asynchronously replicates across Tencent's backbone, eliminating cross-region latency stalls.

Algorithm: Logical Zeroing via Time-Based Versioning

True high-concurrency systems never perform physical deletes or synchronous updates on the hot path. WeChat's "instant zeroing" secret: data is never actually cleared; only the time pointer changes.

Storage Key Design

Keys embed the date: User:Steps:20260515:UIN_12345 → 12,800 steps; User:Steps:20260516:UIN_12345 → 15,400 steps; User:Steps:20260517:UIN_12345 → 0 (uninitialized).

Zero-Point Switch

When the clock ticks from 23:59:59 to 00:00:00, the business layer's date string flips from 20260516 to 20260517. The first post-midnight upload or page view reads/writes the new day's key, which defaults to 0 because it hasn't been initialized. WeChat never iterates 1 billion users to set zeros; it simply moves the write target from "yesterday's plate" to "today's plate" — an O(1) logical reset.

Handling Clock Skew: Delayed Double-Write Window

NTP cannot guarantee perfect alignment across servers and 1 billion phones. Some clients may lag seconds behind, still uploading yesterday's steps after midnight.

To avoid data loss or misattribution, WeChat uses a 5-minute dual-write window (e.g., 23:58–00:03) : incoming step streams increment both yesterday's and today's keys. This guarantees yesterday's champion data stays accurate while today's ledger starts smoothly. After the buffer, yesterday's key becomes read-only cold data awaiting async archival. This is a classic "space-for-time-consistency" trade-off.

Leaderboards: Avoiding Redis BigKeys

Friend Rankings: Lazy Load on Social Graph

There is no global leaderboard. On first open after midnight, the app fetches the user's ~200 friend UINs, does a bulk MGET from memory cache for today's steps, sorts locally in application memory, and renders. This turns an O(N) global write amplification into O(k) read fan-out, naturally staggered by users' own refresh times.

Group Rankings: Hash Sharding by Group_ID

Each group owns a tiny ZSet. WeChat hashes Group_ID across thousands of Redis nodes: Hash(Group_ID) % Redis_Nodes. Even if millions post in groups at midnight, load is physically isolated per node, keeping every server in safe territory.

Cold Data Archival in the Nightly Trough

Past-day keys lingering in expensive memory (Redis/PaxosStore) would explode costs. During the 02:00–04:00 low-traffic window, a distributed scheduler (Flink/batch) quietly:

Async batch archival: Low-priority, throttled threads flush yesterday's frozen data to the persistent sharded database (or HBase).

TTL expiry: Old keys carry a 2–3 day TTL; once safely on disk, memory entries auto-evict.

This hot/cold separation — memory for live concurrency, disk for history — delivers both midnight silkiness and cost control.

Interview Answer Template

When asked to design a 1-billion-user midnight reset system, structure the answer in four steps:

Storage selection: Reject monolithic MySQL; use it only as decoupled archival ledger with strict UIN sharding (e.g., 1024 databases × 1024 tables). Front-end: memory+WAL strong-consistent KV (like PaxosStore) for atomic increments.

Logical zeroing: Zero physical writes at midnight. Key = User:Steps:{Date}:{UIN}. Date pointer flip routes traffic to new key, defaulting to 0. Turns 1 billion clears into O(1) pointer shift.

Clock-skew buffer: 5-minute dual-write window (23:58–00:03) writing to both old and new keys, ensuring accuracy and smooth handover.

Leaderboard & archival: Friend rankings via lazy-loaded friend-graph MGET + in-app sort; group rankings via Group_ID hash sharding. Nightly 02:00–04:00 async flush to persistent store with TTL cleanup.

Technical Essence

The core philosophy: avoid the brute force, leverage structure. Top architects don't optimize physical delete speed; they change the data structure (time-versioned keys) to dissolve a disaster-scale scenario into nothing. Demonstrating "space-for-time", "logical over physical deletion", and "sharding for isolation" mindset signals senior/architect-level system thinking.

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.

Distributed SystemsshardingRedissystem designhigh-concurrencylogical deletionWeChatPaxosStore
ITPUB
Written by

ITPUB

Official ITPUB account sharing technical insights, community news, and exciting events.

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.