Розробка стрічки підписок (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%. Наша команда з 10+ років досвіду та 40+ проєктами у сфері соціальних застосунків гарантує рішення, яке витримає навантаження. Проведемо навантажувальне тестування 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 днів. Вартість розраховується індивідуально. Замовте розробку під ключ та отримайте стабільне рішення для вашого соціального застосунку. Зв'яжіться з нами для оцінки проєкту — гарантуємо прозорий підхід та сертифікованих розробників. Отримайте консультацію інженера.