All system design challenges
#11 Heavy-Read Rankings

App Store Rankings

Rank millions of apps by downloads and ratings per country and category, and serve those lists to a huge read audience.

Asked at Amazon Meta Pinterest

What is being asked

Design the "top charts" of an app store: top free, top paid and top grossing, per country and per category, refreshed periodically and read by everyone who opens the store.

Requirements

Functional

  • Record downloads, purchases and ratings.
  • Produce ranked lists per chart type, country and category.
  • Detect and discount manipulation.

Non-functional

  • Read-heavy by several orders of magnitude.
  • Lists may be minutes to hours old.
  • Reads must be fast worldwide.

Design

Download / purchaseeventsEvent logAggregation jobFraud filterRanking storeChart builderCache / CDNStore clients
Boxes are services; rounded shapes are data stores and queues.
  1. Each download or purchase is appended to an event log.
  2. A job aggregates counts per app per time bucket, per country.
  3. A scoring step combines recent downloads with decay, so yesterday counts more than last month, and applies fraud adjustments.
  4. The chart builder writes complete ranked lists, one per chart, country and category, to a ranking store.
  5. Lists are served through a cache and CDN. A request is a key lookup; nothing is computed at read time.

Key decisions and trade-offs

  • Precompute everything. With reads vastly outnumbering writes, the lists are built offline and served as static data. Freshness is traded for speed and cost.
  • Time decay. A plain total favours old apps for ever. Exponential decay or a rolling window lets new apps rise.
  • Fraud. Bursts of installs from few devices or addresses are discounted before ranking, otherwise charts can be bought.
  • Number of lists. Charts × countries × categories is large but each list is small, so storing all of them is cheap.

Follow-up questions

  • How would you make the chart update within a minute for a launch event?
  • How do you page through a list that changes between requests?
  • How would you personalise the list without losing the caching?
  • What signals would you use to detect paid install farms?
Log in to tick off the challenges you have worked through. Log in