CloudKit: Efficient way to get user's rank in leaderboard without fetching all records?
I'm building a leaderboard feature using CloudKit's public database and need advice on the best approach to calculate a user's rank efficiently.
Current Setup
Record Structure:
Record Type: LeaderboardScore
Fields:
period (String): "daily", "weekly", "monthly", "allTime"
score (Int): User's score
profile (Reference): Link to user's profile
achievedAt (Date): Timestamp
Leaderboard Display:
Initially fetch first 15 users (sorted by score descending)
Paginate to load more as user scrolls
Show total player count
Show current user's rank (even if not in top 15)
The Challenge
I can fetch the first 15 users easily with a sorted query, but I need to display the current user's rank regardless of their position. For example:
User could be ranked #1 (in top 15) ✅ Easy
User could be ranked #247 (not in top 15) ❌ How to get this efficiently?
My Current Approach
Query records with scores higher than the user's score and count them:
// Count how many users scored higher
let predicate = NSPredicate(
format: "period == %@ AND score > %d",
period, userScore
)
// Rank = count + 1
Concerns
For 1000+ users with better scores, this requires multiple paginated queries
Even with desiredKeys: [], I'm concerned about performance and CloudKit request limits
Questions
Is there a CloudKit API I'm missing that can efficiently count records matching a predicate without fetching all the records and paginating?
Is this approach acceptable for a leaderboard with 1K-10K users? Does fetching with desiredKeys: [] help significantly with performance?
Are there any optimizations I should consider to make this more efficient?
What's the recommended approach for calculating user rank in CloudKit at this scale?
Current Scale
Expected: 1,000-10,000 active users per leaderboard period
Platform: iOS 17+, SwiftUI
Any guidance on best practices for leaderboards usecase in CloudKit would be greatly appreciated!