Отметим: когда пользователей тысячи, простой ORDER BY score DESC начинает убивать базу данных. Мы сталкивались с этим в проектах для клиентов из FinTech и EdTech — задержки росли до 5 секунд, а пользователи жаловались на тормоза. Для real-time ранга среди миллиона пользователей используем Redis и специальные структуры данных. В этой статье делимся архитектурными решениями, которые проверены на десятках проектов. Грамотно спроектированный лидерборд — один из самых эффективных инструментов для повышения вовлеченности. Но подходы к реализации сильно различаются в зависимости от масштаба и требований. Ошибки в реализации могут привести к высоким задержкам и плохому пользовательскому опыту.
Рассмотрим три основные категории: до 10 000 пользователей, от 10 000 до миллиона, и более миллиона. Для каждого случая есть оптимальный стек и конфигурация. Мы используем Redis с конфигурацией persistence AOF для надежности, а для периодических лидербордов применяем отдельные ключи с TTL. Также важно правильно определить тип лидерборда: глобальный, периодический, социальный или 'вокруг меня' — каждый решает свои задачи мотивации.
И не забывайте про UX: анимации, кэширование аватаров и плавное обновление ранга критичны для восприятия. В этом материале мы сфокусируемся на технических деталях и лучших практиках, которые помогут избежать типичных ошибок. На клиентской стороне используем кэширование изображений и инкрементальные обновления списка.
Как выбрать технологию для лидерборда в зависимости от масштаба?
До 10 000 пользователей: PostgreSQL + RANK() / DENSE_RANK() window function. Запрос с пагинацией работает быстро даже без специальных индексов. Кешируем топ-100 в Redis с TTL 5 минут.
10 000 – 1 000 000 пользователей: Redis Sorted Sets (ZADD, ZRANK, ZREVRANK, ZREVRANGE). Добавление очков: ZADD leaderboard:global NX <score> <user_id> или ZINCRBY leaderboard:global <delta> <user_id>. Получение ранга пользователя: ZREVRANK leaderboard:global <user_id> — O(log N). Топ-100: ZREVRANGE leaderboard:global 0 99 WITHSCORES — O(log N + 100). Это работает без деградации даже на миллионе пользователей.
Миллионы пользователей: шардирование Redis Sorted Set по временным периодам и регионам. Глобальный лидерборд превращается в недостижимую цель для большинства — демотивирует. Лучше сегментировать.
| Масштаб | Технология | Производительность |
|---|---|---|
| До 10К | PostgreSQL | Быстро, кеш топ-100 |
| 10К – 1M | Redis | O(log N) на операцию |
| >1M | Redis + шардирование | Линейное масштабирование |
Типы лидербордов и их особенности
| Тип | Описание | Мотивация |
|---|---|---|
| Глобальный (all-time) | Общий рейтинг всех пользователей | Высокая для топ-10, низкая для остальных |
| Периодический (неделя/месяц) | Сбрасываемый рейтинг | Равная для всех, гонка за лидерство |
| Социальный (друзья) | Только среди друзей | Очень высокая, здоровое соперничество |
| «Вокруг меня» | Пользователь и соседние позиции | Мотивирует видеть свой прогресс |
Временные периоды лидерборда
Глобальный «all time» — для топ-игроков. Еженедельный и ежемесячный — для всех остальных. Сброс в начале периода: не удаляем данные, архивируем. Пользователь должен видеть свои прошлые результаты.
Реализация сброса: отдельный ключ для каждого периода leaderboard:weekly:YYYY-WW, leaderboard:monthly:YYYY-MM. По истечении периода создаём новый ключ — старый остаётся для истории. TTL на старые ключи: 30 дней для недельных, 90 для месячных.
Почему лидерборд «вокруг меня» повышает вовлечённость?
Самый полезный вид лидерборда для среднего пользователя. Не «топ-100», а «ты на месте 4573, вот 5 человек выше и 5 ниже». Мотивирует тех, кто никогда не войдёт в топ.
Реализация на Redis: ZREVRANK для получения ранга пользователя, затем ZREVRANGE(rank-5, rank+5) для соседних позиций. Дополнительный запрос к PostgreSQL для получения display name и аватара по user_id из результата.
Социальные лидерборды
Лидерборд среди друзей — часто мотивирует сильнее, чем глобальный. Реализация сложнее: нет смысла в глобальном sorted set для списка из 50 друзей.
Вариант 1: при открытии экрана делаем запрос к PostgreSQL: SELECT user_id, score FROM user_scores WHERE user_id IN (:friends_list) ORDER BY score DESC. Работает при небольшом числе друзей (до 200).
Вариант 2: отдельный sorted set для каждого пользователя leaderboard:user:<user_id>:friends — обновляем при каждом изменении очков любого друга. Дороже по памяти Redis (примерно 1.5x), зато мгновенное чтение.
Отображение и UX
Подсветка позиции текущего пользователя в списке — обязательно. Анимированное обновление ранга при получении новых очков (ScrollTo + highlight). Стрелки роста/падения рядом с позицией — «ты вырос на 12 мест за сегодня». Историческая кривая ранга пользователя за период.
На Flutter: AnimatedList для smooth обновлений. На iOS: UITableView с performBatchUpdates. На Android: RecyclerView с DiffUtil. Не перезагружай весь список при обновлении — только изменившиеся ячейки (в среднем 3-5).
Аватары в лидерборде — кешируй агрессивно. SDWebImage (iOS) / Glide (Android) / cached_network_image (Flutter) с disk cache (размер до 50 МБ). Не показывай лидерборд без имён и аватаров — только скелетон во время загрузки.
Процесс разработки лидерборда под ключ
- Аналитика и архитектура: изучаем требования, выбираем стек (Redis + PostgreSQL), проектируем API.
- Реализация бэкенда: настройка Redis Sorted Sets, разработка эндпоинтов для получения ранга и топа.
- Клиентская часть: интеграция на iOS (Swift), Android (Kotlin) или Flutter с анимациями и кэшированием.
- Интеграция с системой аутентификации: связываем с существующей базой пользователей.
- Документация и тестирование: нагрузочное тестирование (до 10 000 RPS), проверка real-time производительности.
- Деплой и поддержка: развертывание на серверах, месяц бесплатного сопровождения.
Что входит в работу
- Документация по архитектуре и API
- Доступ к репозиторию с исходным кодом
- Инструкция по развертыванию и настройке (включая конфиги Redis)
- Обучение команды работе с лидербордом
- Месяц технической поддержки после запуска
Наш опыт
Мы разрабатываем мобильные приложения с геймификацией более 5 лет. В портфолио — 50+ проектов, включая лидерборды для финтех-, edtech- и игровых приложений. Гарантируем стабильную работу под нагрузкой до 10 миллионов пользователей. — Отдел мобильной разработки.
Пример конфигурации Redis для лидерборда
# redis.conf save 900 1 save 300 10 save 60 10000 appendonly yes appendfsync everysec Ключи: leaderboard:global, leaderboard:weekly:YYYY-WW, leaderboard:user:{userId}:friends.
Ориентиры по срокам
Базовый лидерборд с недельным/месячным периодом и рангом пользователя — 2–3 дня (клиент) + 2–3 дня (бэкенд на Redis). С социальным лидербордом, «вокруг меня», историей рангов и real-time обновлениями — 1–2 недели. Стоимость базовой реализации — от 150 000 до 300 000 рублей. Ежемесячная экономия на серверной инфраструктуре — до 50 000 рублей. Стоимость рассчитывается индивидуально. Закажите консультацию — мы оценим ваш проект за один день. Получите рекомендации по архитектуре и стеку, даже если вы только на этапе идеи.
Свяжитесь с нами, чтобы обсудить внедрение лидерборда в ваше приложение.







