M5 Design WeChat Steps Ranking
Loading learning experience...
Lecture transcript
Read the narration for M5: Design WeChat Steps Ranking
From experiments to rankings: same discipline, new traps
Dr. Wei: Last time, on experimentation platforms, the key takeaway was: define the lifecycle end to end, and use deterministic hashing so a user stays in the same variant across sessions.
Dr. Wei: Today we reuse that same mindset: define the lifecycle of step data, then prove with numbers why the naive ranking approach explodes in cost.
Sam: I check WeChat steps daily, but I never thought a friends-only leaderboard could be harder than a global one.
Sam: Is the key reason that the read is scoped to friends, but the writes are still per person and happen all day, so the combination creates an explosion?
Why this is a masterclass in write amplification
Dr. Wei: This system looks simple until you multiply: users times updates times friends. That multiplication is the whole interview.
Dr. Wei: By the end, you will know when precomputing ranks is a win, and when it is financially impossible.
Sam: I feel like Redis ZSET is the obvious answer. I guess that is the trap?
Sam: Before we do numbers, what freshness are we aiming for in the product, and how strict is it? That seems like it will decide whether we can compute on demand.
Scope the product like an $IC6$: what we build, what we skip
Dr. Wei: Meta interviewers reward candidates who drive ambiguity. Let us scope crisply before architecture. In WeChat Steps Ranking, we want a clear definition of the user promise: what problem we solve on day one, for whom, and what we intentionally do not build yet.
Dr. Wei: So at a high level, the first release should focus on a simple loop: accept step updates, compute each user’s daily total, and show a ranking against friends. Anything that does not strengthen that loop is a candidate to defer.
Dr. Wei: As we scope, we also need guardrails: privacy expectations and cheating resistance are part of the core experience, not nice-to-haves. At the same time, we avoid expanding into features like a global leaderboard or a social feed until the core ranking experience is solid and measurable.
Sam: When we say privacy is core, do we assume users must opt in, and only confirmed friends can see them? Also, do we ever need blocking or hiding specific friends in the first version?
Estimate scale: the math that chooses the architecture
Sam: Before we land on a design, can we sanity-check the scale numbers? Roughly, how many step updates per second and leaderboard reads per second do we expect at one hundred million daily active users?
Dr. Wei: updates per second is approximately one hundred million times ten divided by eighty six thousand four hundred.
Dr. Wei: reads per second is approximately one hundred million times two divided by eighty six thousand four hundred.
API surface: minimal, enforceable, cache-friendly
Dr. Wei: A clean API is a design tool: it forces you to define identity, freshness, and authorization boundaries.
Dr. Wei: For a steps ranking feature, we want a surface area that is small but strict: every request should clearly say who the user is, which day we mean, and what data can be returned.
Dr. Wei: The goal is enforceable rules and cache-friendly reads: updates should be explicit, and reads should be stable so they can be safely cached without leaking private information or showing stale rankings.
Sam: For the update call, do we want to accept absolute daily totals, or incremental deltas? Absolute totals seem idempotent, but deltas might be smaller and more frequent.
Data model: make the date part of the key
Dr. Wei: To make a daily leaderboard work well, we want each day to feel like a fresh, separate space for reads and writes.
Sam: So instead of clearing yesterday’s data, we separate it by design?
Dr. Wei: Exactly. If the date is part of the key, a new day naturally shifts traffic to a new key range. That avoids a risky mass delete, makes caching safer, and keeps backfills or late uploads from corrupting today’s results.
Baseline design: on-demand ranking at read time
Sam: If we compute rankings on demand, what is the basic shape of the read path? I want to make sure I understand what work happens when I open the leaderboard.
Dr. Wei: We start with the simplest correct design, then optimize with evidence. Baseline idea: do the ranking when the user opens the leaderboard, even if that means more work on the read path.
Dr. Wei: At a high level, the server looks up who your friends are, fetches each friend’s step count, sorts everyone, and returns the top results. This keeps the data model straightforward and makes correctness easy to reason about.
Dr. Wei: The tradeoff is performance at read time: as your friend list grows, each read must do more lookups and more sorting work. This baseline is our reference point, so later we can justify any added complexity by showing which part of this read-time cost we are reducing.
Sam: If the average friend count is a few hundred, sorting seems fine, but the worst case friend count could be thousands. Would we cap the ranking to, say, the first five thousand friends, or do we need a different strategy for outliers?
Tempting but deadly: precomputed per-user Redis ZSET
Dr. Wei: Let’s consider a very tempting design choice for a friends ranking system: instead of computing rankings on demand, we precompute and store a dedicated sorted set for each user and each day.
Dr. Wei: Before we do any math, I want a gut check: if every step update has to be pushed into many friends’ leaderboards, how many Redis writes per day do you think this causes—millions, billions, or trillions?
Dr. Wei: Now reveal the multiplication: about one hundred million users times around ten updates each per day times roughly three hundred friends means about three hundred billion ZSET writes per day. That gap between the intuitive guess and the computed number is why this approach melts down at scale.
Sweet spot: on-demand $+$ cache the computed leaderboard
Dr. Wei: The sweet spot here is to keep the write path almost trivial, and spend computation only when someone actually asks to see a ranking. Then we reuse that work by caching the computed leaderboard for a short time window, so repeated opens feel fast without turning every step update into heavy server work.
Sam: If we cache each user’s leaderboard for about five minutes, what kind of cache hit rate should we expect? My guess is maybe 70 to 90 percent, since people often reopen the Steps screen within a few minutes.
Dr. Wei: That’s a good starting point, but let’s pressure-test it. Heavy users might refresh frequently, which helps hits, but a large friend set and many distinct users can churn the cache. Also, traffic is spiky: after a push notification, many people open once and never come back within five minutes, which lowers the hit rate.
Sam: So maybe we should plan for something like 60 to 80 percent hits in normal conditions, and lower during spikes. How does that translate into how much compute we actually do per second?
Dr. Wei: Exactly. If compute per second is roughly reads per second times one minus h, then with a 70 percent hit rate you only compute on about 30 percent of reads. Using our earlier global estimate of about two thousand three hundred reads per second, that’s roughly six hundred ninety leaderboard computations per second; at 80 percent hits, it drops to about four hundred sixty. That’s why a small TTL cache can make on-demand ranking practical.
Midnight reset and time zones: correctness without cron jobs
Dr. Wei: The midnight reset sounds like a scheduling problem, but it is really a correctness problem about how you define what “today” means for each user.
Dr. Wei: Instead of deleting yesterday’s data at midnight, we model each day as a separate keyspace by including the date in the partition key. When the date changes, reads and writes naturally move to a new partition, so there is nothing to clean up in the hot path.
Dr. Wei: The tricky part is computing the date safely. We should not trust a client supplied locale or time zone, because users can change it and people can travel. A concrete policy is: compute the day using server time plus a stored per user time zone, then lock that time zone for the rest of the day so travel only affects the next day’s partition. For retention, keep leaderboard caches on a short TTL like minutes, but keep the step rows much longer, like 7 to 30 days or with hot and cold storage, so you can recompute and audit. Then define a late update rule: accept uploads into yesterday within a grace window, and after that window, freeze the day’s results.
Sam: What happens with late arriving updates, like the phone being offline and uploading yesterday’s steps after midnight? Do we accept it into yesterday’s partition, and do we ever show backfilled changes in a cached leaderboard?
Anti-cheating and privacy: enforce at the service boundary
Dr. Wei: Any public ranking creates pressure to cheat. If we treat integrity as an afterthought, the leaderboard becomes a contest of who can exploit the system, not who actually walks.
Dr. Wei: Before we talk about enforcement, be clear about what the backend can and cannot verify. Some signals can be stronger, like device or app integrity checks from the platform, and sensor-based patterns that look like real walking, but the step count itself is still, in part, self-reported by the app ecosystem and can be manipulated.
Dr. Wei: So the core idea is to enforce anti-cheating and privacy at the service boundary, where every update must pass the same checks. Treat attestation as best-effort evidence, then back it up with sanity rules over time, throttling, and privacy gating before it can affect anyone else’s ranking.
Sam: How strict should we be on enforcement? For example, if someone is not enrolled or not a friend, do we hide them entirely from the ranking, or show them with masked details? And do we ever allow viewing without being visible?
Failure modes and tradeoffs: what Meta interviewers probe
Dr. Wei: Let’s step back and evaluate the design the way an interviewer would: not just whether it works on a good day, but how it behaves when parts of the system are slow, missing, or returning inconsistent data.
Dr. Wei: In this section, the goal is to surface failure modes and tradeoffs: what we are optimizing for, what we are willing to degrade, and what we refuse to break, especially for a social ranking product like WeChat steps.
Dr. Wei: As we go, think in terms of priorities: correctness versus freshness, latency versus cost, and user trust. Also be ready to explain what you would ship first, and what you would add later as you level up the design.
Sam: If we have to degrade during an outage, what is the user-facing priority order? For example, is it better to show a cached but slightly stale ranking, or to show an error but guarantee correctness?
Exit ticket: prove the ZSET approach is infeasible
Dr. Wei: Exit ticket time. Your job is to show, with a quick back-of-the-envelope argument, why a ZSET-per-user style approach blows up at WeChat scale.
Dr. Wei: Compute the total work W using three knobs: U users, k updates per user, and F friends per user. We are not chasing perfect precision; we are sanity-checking the order of magnitude.
Dr. Wei: Then do a design reflection: if the cost is too high and you need a ten times reduction, which product promise would you relax first. For example, would you allow rankings to be slightly stale, reduce how many friends you consider, or limit how often we recompute during bursts.
Thank you for watching!
Thanks for watching. Subscribe and share if you found this useful—see you next time!