We spent two weeks building the Play Quotient — a cross-game skill score that decays with inactivity, rewards consistency, and accounts for diversity across games. It’s elegant. It’s well-calibrated. And it’s completely useless for weekly leagues.

Here’s why: PQ is a compressed score. It sits on a base of 1000, and the delta between a casual player and a hardcore one is only about 100-200 points. A 3-day player might be PQ 1026. A 6-month daily player might be PQ 1121. The spread is narrow by design — PQ is a skill identity badge, not an engagement metric.

But leagues need movement. If everyone’s PQ delta for the week is between 0 and 15, there’s no meaningful promotion or demotion. Half the league stays in exactly the same tier. That’s not a competition — it’s a participation ribbon.

The math that changed our mind

I ran the numbers. Over a typical week:

Player typeWeekly XPWeekly PQ delta
Casual (3 sessions)~150~2-3
Regular (10 sessions)~800~8-12
Hardcore (25 sessions)~2,500~20-30
Nobody-sleeps (50 sessions)~8,000~50-80

The PQ delta range is 0-80 across all players. But within any given league tier (say, 50 players), most are bunched within 10 points of each other. The difference between rank 5 and rank 45 is a single Cabo game. That’s not a weekly competition — it’s noise.

Weekly XP delta, on the other hand, spans from 0 to 10,000+. The ratio between a casual player (150 XP) and a hardcore player (2,500 XP) is 16:1. With PQ delta, it’s 4:1. The engagement signal is simply much stronger in XP.

Duolingo uses XP for leagues, not a skill score. We independently discovered why. Engagement and skill are different axes. Leagues should run on engagement.

The two metrics coexist

This isn’t about replacing PQ. It’s about using the right metric for the right purpose:

  • PQ (Play Quotient) — long-term skill identity. Displayed on profiles. Decays with inactivity. Slow-moving. A badge of honor.
  • weeklyXPDelta — this week’s engagement. Drives league promotion and demotion. Resets every Monday. Fast-moving. A competition.

PQ tells you “how good is this player overall?” Weekly XP tells you “how much did they play this week?” For leagues, the second question is the one that matters.

Why Duolingo was right

Duolingo’s leagues run on weekly XP, not cumulative skill. When I first saw this, I thought it was a design flaw — shouldn’t leagues reward skill? But the data is clear: weekly XP drives daily engagement. Players who see their league position move are more likely to play another session. Players who see a flat PQ delta of +2 are not.

The key insight: leagues are a retention mechanic, not a ranking system.Their job is to make you want to play one more game this week, not to determine who is objectively the best player. The best players already know they’re the best — they don’t need a league to tell them. The people who need the league are the ones who are thinking about leaving.

The implementation

Every Monday at 7 AM IST (prod), the league scheduler runs:

LeagueService.java (simplified)
java
for each active user (weeklyXPDelta > 0):
  previousLeague = getPreviousWeekLeague(uid)
  
  if weeklyXPDelta > promotionThreshold:
      newLeague = previousLeague.nextLeague()
      creditReward(newLeague)
  else if weeklyXPDelta < demotionThreshold:
      newLeague = previousLeague.previousLeague()
  else:
      newLeague = previousLeague  // stay in same tier
  
  saveLeagueAssignment(uid, newLeague, currentWeekCode)

Note: inactive users (weeklyXPDelta == 0) are skipped entirely. They keep their current league — even if they haven’t played in weeks. This is the “ghosting paradox”: an inactive Diamond player stays Diamond, while an active Silver player who played hard but fell slightly short stays Silver. It feels wrong, but the alternative (demoting inactive users) creates a “welcome back to Bronze” experience that’s worse.

The 52-tier ladder

We started with 5 ranks: Rookie, Sharp, Clever, Genius, Mastermind. Five tiers for thousands of players. A casual player in Rookie would need to grind for months before reaching Sharp. And once you’re in Mastermind, there’s nowhere to go.

52 tiers — Bronze through Legendary — solves both problems. There’s always another tier to reach, and the thresholds are close enough that meaningful movement happens every week. A player who goes from Bronze 1 to Bronze 3 still has Bronze 4, Bronze 5, Silver 1, Silver 2, and so on to look forward to.

The ladder is Remote Config-driven. Each tier has promotionThreshold and demotionThreshold in weekly XP, and a pqLeague flag so legacy tiers can coexist. If the thresholds feel wrong, we adjust them in Firebase Remote Config — no app update required.

What I’d Tell My Past Self

  1. Leagues run on engagement, not skill. PQ is the right metric for profiles. Weekly XP is the right metric for leagues.
  2. More tiers means more movement. 5 tiers create stagnation. 52 tiers create weekly momentum.
  3. Don’t demote inactive users. A “welcome back to Bronze” experience kills retention. Let them keep their league — they’ll demote naturally when they start playing again.
  4. Remote Config your thresholds. You’ll adjust them at least twice. Make it a config change, not an app update.
  5. Duolingo got there first. Read their engineering blog. They solved the same problem and landed on the same answer.