Разработка ленты подписок (Following Feed) в мобильном приложении

Сделать ленту подписок (following feed) в мобильном приложении, работающую при 100K+ подписчиков, — нетривиальная задача. Простой SQL-запрос `SELECT * FROM posts WHERE author_id IN (SELECT followee_id FROM follows WHERE follower_id = :user) ORDER BY created_at DESC` ломается при масштабировании: на

Разработка и поддержка любых видов мобильных приложений:

Информационные и развлекательные мобильные приложения
Новостные приложения, игры, справочники, онлайн-каталоги, погодные, фитнес и здоровье, туристические, образовательные, социальные сети и мессенджеры, квиз, блоги и подкасты, форумы, агрегаторы
Мобильные приложения электронной коммерции
Интернет-магазины, B2B-приложения, маркетплейсы, онлайн-обменники, кэшбэк-сервисы, биржи, дропшиппинг-платформы, программы лояльности, доставка еды и товаров, платежные системы
Мобильные приложения для управления бизнес-процессами
CRM-системы, ERP-системы, управление проектами, инструменты для команды продаж, учет финансов, управление производством, логистика и доставка, управление персоналом, системы мониторинга данных
Мобильные приложения электронных услуг
Доски объявлений, онлайн-школы, онлайн-кинотеатры, платформы предоставления электронных услуг, платформы кешбека, видеохостинги, тематические порталы, платформы онлайн-бронирования и записи, платформы онлайн-торговли

Это лишь некоторые из типы мобильных приложений, с которыми мы работаем, и каждый из них может иметь свои специфические особенности и функциональность, а также быть адаптированным под конкретные потребности и цели клиента.

Услуги, которые мы предлагаем
Показано 1 из 1Все 1734 услуг
Разработка ленты подписок (Following Feed) в мобильном приложении
Средний
~2-3 дня

Наши компетенции:

Часто задаваемые вопросы

Последние работы

  • image_mobile-applications_feedme_467_0.webp
    Разработка мобильного приложения для компании FEEDME
    895
  • image_mobile-applications_xoomer_471_0.webp
    Разработка мобильного приложения для компании XOOMER
    782
  • image_mobile-applications_rhl_428_0.webp
    Разработка мобильного приложения для компании RHL
    1216
  • image_mobile-applications_zippy_411_0.webp
    Разработка мобильного приложения для компании ZIPPY
    1079
  • image_mobile-applications_affhome_429_0.webp
    Разработка мобильного приложения для компании Affhome
    1002
  • image_mobile-applications_flavors_409_0.webp
    Разработка мобильного приложения для компании FLAVORS
    597

Сделать ленту подписок (following feed) в мобильном приложении, работающую при 100K+ подписчиков, — нетривиальная задача. Простой SQL-запрос SELECT * FROM posts WHERE author_id IN (SELECT followee_id FROM follows WHERE follower_id = :user) ORDER BY created_at DESC ломается при масштабировании: на 1 млн подписчиков и 10 млн постов время ответа превышает 3 секунды. Добавьте realtime, необходимость мгновенного старта и популярного автора с миллионом подписчиков — и без продуманной архитектуры не обойтись. Гибридная схема fan-out для обычных и fan-in для звёзд снижает затраты на инфраструктуру на 30-50%. Наша команда с 7+ лет опыта и 50+ проектами в сфере социальных приложений гарантирует решение, которое выдержит нагрузку. Проведём нагрузочное тестирование k6 на 1000 rps — и только после этого сдаём проект.

Как выбрать архитектуру для разработки ленты подписок: fan-in или fan-out?

Два классических подхода: fan-out on write (push) и fan-in on read (pull). При fan-out публикация поста сразу записывается в ленты всех подписчиков — чтение становится быстрым, но запись дорогой для популярных авторов. Fan-in, наоборот, при запросе собирает посты из подписок — нет дублирования данных, но чтение может быть медленнее. На практике применяют гибрид: fan-out для обычных пользователей (до 100K подписчиков у автора) и fan-in для «звёзд» с миллионами фолловеров. Порог настраивается. Для MVP достаточно fan-in:

SELECT p.*, u.name, u.avatar_url FROM posts p JOIN follows f ON p.author_id = f.followee_id JOIN users u ON p.author_id = u.id WHERE f.follower_id = :user_id AND p.created_at < :cursor ORDER BY p.created_at DESC LIMIT 20; 

Индексы: follows(follower_id), posts(author_id, created_at DESC). С таким запросом при 1 млн подписок время ответа — 100-150 мс.

Характеристика Fan-out on write Fan-in on read
Скорость чтения O(1) — моментально O(N) — может быть медленным при 1M+ подписок
Скорость записи для звезды Очень дорого (миллионы копий) O(1) — только запись поста
Хранение Много дублирования (50+ копий на пост) Минимум дублирования
Нагрузка на сервер Высокая на запись, низкая на чтение Низкая на запись, высокая на чтение
Масштабирование Сложно для популярных авторов Хорошо для любого количества подписчиков

Cursor-based пагинация: преимущества перед offset

Cursor-пагинация обрабатывает запрос за 50 мс при таблице в 10 млн строк, тогда как OFFSET на 100-й странице — до 2 секунд. Используем cursor = created_at последнего поста (ISO 8601): GET /feed?cursor=LAST_SEEN_POST_TIMESTAMP&limit=20 Ответ: { items: [...], next_cursor: "...", has_more: true }.

Реализация простая: индекс на (created_at) обеспечивает O(log n). В отличие от OFFSET, cursor не чувствителен к вставкам — дубли не появляются.

Как обеспечить мгновенную загрузку ленты?

Кэширование на клиенте — ответ. На iOS с Swift сохраняем первые 50-100 постов ленты в CoreData или Realm. При открытии приложения — мгновенно показываем кэш, одновременно запрашиваем новые посты. Когда новые посты пришли — тихо вставляем их в начало или показываем баннер. NSFetchedResultsController + NSDiffableDataSourceSnapshot для плавного обновления без мерцания. На Android с Kotlin используем Room + Paging 3 с RemoteMediator. Локальная база — источник истины, RemoteMediator подгружает данные из сети в Room, Paging 3 рендерит из Room. На Flutter — Hive или Isar для локального кэша, flutter_bloc для управления состоянием страниц.

Платформа Кэширующая технология Библиотека для изображений Преимущества
iOS (Swift) CoreData / Realm Kingfisher NSFetchedResultsController, DiffableDataSource
Android (Kotlin) Room + Paging 3 Coil RemoteMediator, интеграция с Compose
Flutter (Dart) Hive / Isar cached_network_image Простота, fast startup

Кэш позволяет сократить загрузку данных при старте на 80% и снизить расход трафика.

Realtime-обновления: стратегии и реализация

  • Pull to refresh — пользователь тянет вниз, запрашиваем посты новее firstPost.created_at. Самый простой, работает везде.
  • WebSocket/SSE — сервер пушит новые посты клиенту. Показываем баннер «N новых постов» вверху ленты (как Twitter). Клиент не вставляет их автоматически — только по тапу на баннер, иначе лента прыгает под пальцем.
  • Long polling — компромисс без WebSocket.

На iOS WebSocket — URLSessionWebSocketTask. На Android — OkHttp WebSocket. На Flutter — web_socket_channel.

Настройка realtime-обновлений через WebSocket

  1. Создайте WebSocket-соединение при входе в ленту.
  2. Сервер отправляет событие new_post с ID поста.
  3. Клиент отображает баннер «X новых постов».
  4. По тапу на баннер загружаем недостающие посты через API.

Алгоритмическая лента

Хронологическая лента — базис. Если нужна алгоритмическая (ранжирование по engagement): хранить score за каждый пост, пересчитывать через воркер (BullMQ/Celery) при добавлении лайков/комментариев. Клиент запрашивает ленту с параметром sort=ranked. Для первого запуска — хронологическая, после набора данных — переключение на алгоритмическую. Обе ленты как отдельные вкладки (Reels vs Following у Instagram).

Скролл и производительность

UICollectionView с UICollectionViewCompositionalLayout и DiffableDataSource — золотой стандарт на iOS. Prefetch данных через UICollectionViewDataSourcePrefetching. Изображения — Kingfisher с кэшированием в памяти и на диске. На Android LazyColumn (Compose) или RecyclerView с ConcatAdapter. Изображения — Coil с rememberAsyncImagePainter. Главная причина дёрганой прокрутки — декодировка изображений на main thread. Kingfisher и Coil делают это в background по умолчанию. При кастомной загрузке — DispatchQueue.global(qos: .userInitiated).async (iOS) или Dispatchers.IO (Android).

Что входит в работу

  • Архитектурная схема ленты (выбор fan-in/fan-out/гибрид) под вашу нагрузку.
  • API с cursor-пагинацией и realtime-событиями.
  • UI ленты с кэшем и плавной прокруткой.
  • Нагрузочное тестирование (k6) на сценарий «1000 запросов ленты одновременно».
  • Документация, код и поддержка при деплое.

Этапы разработки ленты подписок

  1. Анализ нагрузки: ожидаемое количество подписчиков, TPS, размер поста.
  2. Выбор архитектуры: fan-in/fan-out/гибрид, порог для звёзд.
  3. Проектирование API: REST + WebSocket, cursor-пагинация.
  4. Реализация UI: коллекция/список с кэшем и prefetch.
  5. Realtime-интеграция: WebSocket/SSE, баннер новых постов.
  6. Нагрузочное тестирование: k6, 1000 rps, мониторинг.
  7. Деплой и мониторинг: CI/CD, логи, алерты.

Сроки

Базовая лента с pull-to-refresh и пагинацией — 2-3 дня. С realtime WebSocket, кэшем, алгоритмическим ранжированием — 7-10 дней. Стоимость рассчитывается индивидуально. Закажите разработку под ключ и получите стабильное решение для вашего социального приложения. Свяжитесь с нами для оценки проекта — гарантируем прозрачный подход и сертифицированных разработчиков. Получите консультацию инженера.