Розробка стрічки підписок (Following Feed) у мобільному застосунку

TRUETECH займається розробкою, підтримкою та обслуговуванням мобільних додатків iOS, Android, PWA. Маємо великий досвід та експертизу для публікації мобільних додатків до популярних маркетів Google Play, App Store, Amazon, AppGallery та інші.

Розробка та підтримка будь-яких видів мобільних додатків:

Інформаційні та розважальні мобільні програми
Новинки, ігри, довідники, онлайн-каталоги, погодні, фітнес та здоров'я, туристичні, освітні, соціальні мережі та месенджери, квіз, блоги та подкасти, форуми, агрегатори
Мобільні програми електронної комерції
Інтернет-магазини, B2B-додатки, маркетплейси, онлайн-обмінники, кешбек-сервіси, біржі, дропшиппінг-платформи, програми лояльності, доставка їжі та товарів, платіжні системи
Мобільні програми для управління бізнес-процесами
CRM-системи, ERP-системи, управління проектами, інструменти для команди продажів, облік фінансів, управління виробництвом, логістика та доставка, управління персоналом, системи моніторингу даних
Мобільні програми електронних послуг
Дошки оголошень, онлайн-школи, онлайн-кінотеатри, платформи надання електронних послуг, платформи кешбеку, відеохостинги, тематичні портали, платформи онлайн-бронювання та запису, платформи онлайн-торгівлі

Це лише деякі з типів мобільних додатків, з якими ми працюємо, і кожен із них може мати свої специфічні особливості та функціональність, а також бути адаптованим під конкретні потреби та цілі клієнта.

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

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

Етапи розробки

Останні роботи

  • image_mobile-applications_feedme_467_0.webp
    Розробка мобільного додатка для компанії FEEDME
    858
  • image_mobile-applications_xoomer_471_0.webp
    Розробка мобільного додатку для компанії XOOMER
    743
  • image_mobile-applications_rhl_428_0.webp
    Розробка мобільного додатку для компанії RHL
    1160
  • image_mobile-applications_zippy_411_0.webp
    Розробка мобільного додатку для компанії ZIPPY
    1034
  • image_mobile-applications_affhome_429_0.webp
    Розробка мобільного додатку для компанії Affhome
    968
  • image_mobile-applications_flavors_409_0.webp
    Розробка мобільного додатку для компанії FLAVORS
    562

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

Розробка чатів та соціальних функцій: чат, VoIP, стрічка та реакції

Ми проектуємо чат не як «просто WebSocket + повідомлення», а як систему з офлайн-доступом, відображенням історії при поганому з'єднанні, індикаторами друку, статусами прочитання та push-повідомленнями. Це має працювати на Android 8 з 512 MB RAM без ANR — інакше користувачі просто йдуть. Ми маємо 5+ років досвіду у розробці соціальних модулів, понад 50 реалізованих проектів — від стартапів до enterprise. Розробка чатів — наш ключовий напрям.

Як ми підходимо до розробки чатів?

Вибір протоколу та сховища — перша точка, де помиляються. WebSocket, XMPP або готовий SDK — кожен варіант диктує бюджет часу та надійність.

Як обрати протокол для чату?

  • Готовий чат SDK (SendBird, Stream Chat, Cometchat) дає UI-компоненти, серверну інфраструктуру, push та модерацію. Швидко, надійно, але vendor lock-in та recurrent costs. Для MVP — оптимально. Ліцензія SendBird для проекту з 10К користувачів — ~$400/міс.
  • Firebase Realtime Database / Firestore — для простих чатів без вимог до масштабованості >100K конкуретних з'єднань. Realtime Database зручніше для впорядкованих списків повідомлень, Firestore — для структурованих даних. Typing indicators та presence реалізуються окремо через onDisconnect().
  • Власний бекенд з WebSocket — повний контроль, максимальна кастомізація. Стек: Node.js + socket.io або Phoenix Channels (Elixir), PostgreSQL + Redis для pub/sub. На мобільному: Starscream (iOS Swift), OkHttp WebSocket (Android), socket_io_client (Flutter). Час розробки в 2–3× більше, але zero vendor risk. Кастомний WebSocket дає в 2 рази меншу затримку, ніж Firebase для високочастотних чатів. В одному проекті ми обрали кастомний WebSocket і зменшили витрати на ліцензії на $12 000 на рік.
Функція Готовий SDK Кастомна реалізація
Базовий чат SendBird, Stream WebSocket + Room/GRDB
VoIP Twilio, Agora WebRTC + CallKit
Стрічка Paging 3 / DiffableDataSource
Push для соц. подій Firebase FCM/APNs APNs direct

Чому важливо продумувати офлайн-режим заздалегідь?

Офлайн-режим — найтрудомісткіша частина чату. Повідомлення зберігаються в SQLite (iOS: GRDB, Android: Room) з локальним ID, синхронізуються при відновленні з'єднання. Конфлікти при одночасному відправленні вирішуються через vector clock або server-timestamp ordering. Якщо не закласти це в архітектуру з першого спринту, переписувати половину коду доведеться за 2–3 тижні до релізу. В одному проекті ми скоротили час переписування з 4 до 1,5 тижня, застосувавши cursor-based pagination замість offset — при вставці нових елементів курсор не зсувається, дублі не виникають. Середня затримка доставки повідомлення після оптимізації — менше 150 мс.

VoIP: CallKit, ConnectionService та WebRTC

VoIP у мобільному додатку розбивається на два сценарії: системний UI (виглядає як дзвінок телефону) або дзвінок всередині додатку. CallKit (iOS) інтегрується через CXProvider + CXCallController — показує вхідний виклик на Lock Screen, працює з Bluetooth та перериває інші аудіо. Додаток запускається через VoIP push (PKPushKit) навіть коли вбито.

На Android аналог — ConnectionService API. Інтеграція складніша, поведінка варіюється між виробниками (Xiaomi, Samsung агресивно вбивають фонові процеси через battery optimization). WebRTC — транспорт для P2P медіа. Сигнальний сервер (SDP, ICE candidates) — зазвичай через той же WebSocket канал. STUN/TURN обов’язкові: без TURN ~15–20% користувачів за симетричним NAT не побачать виклик. coturn — open source рішення, Twilio NTS та Metered TURN — managed.

Стрічка та реакції

Нескінченна стрічка — UICollectionView з UICollectionViewDiffableDataSource на iOS, LazyColumn з Paging 3 на Android. Pagination через cursor-based підхід — він не зсувається при вставці нових елементів, на відміну від offset. Реакції (емодзі на повідомлення): кожна реакція — запис (message_id, user_id, emoji), агрегація на сервері GROUP BY emoji. WebSocket-подія reaction_added оновлює лічильник у реальному часі. Анімація появи — через withSpring (Reanimated) або Core Animation spring. У проекті з соціальною мережею ми обслуговували до 80 000 одночасних з’єднань на одному інстансі — стрічка залишалася чуйною.

Push-повідомлення для соціальних подій: @згадка, відповідь, новий підписник — через APNs та FCM. Для rich notifications (прев’ю медіа) на iOS — Notification Service Extension, який завантажує медіа до показу. Після впровадження таких повідомлень утримання користувачів зросло на 30%.

Що входить в роботу: повний список deliverables

Ми постачаємо не тільки код — ось повний перелік того, що ви отримуєте:

  1. Проектування схеми даних (SQLite, Firestore, PostgreSQL) з урахуванням offline-first та масштабування до 1M користувачів.
  2. Реалізація клієнт-серверного протоколу (WebSocket, REST, GraphQL) з підтримкою reconnection та heartbeat.
  3. Інтеграція push-повідомлень (APNs, FCM) з генерацією сертифікатів та налаштуванням ключів.
  4. Налаштування TURN-серверів або вибір managed-провайдера (наприклад, Twilio NTS) для VoIP.
  5. Документація API та схема міграцій (включаючи rollback-план).
  6. Доступ до репозиторію, CI/CD (GitHub Actions + Fastlane), TestFlight / Google Play Console.
  7. Навчання команди (code review перших 2 спринтів) та передача знань.
  8. On-call підтримка протягом 2 тижнів після релізу.

Типові помилки при розробці чатів та як їх уникнути

  • Відсутність reconnection стратегії. Клієнт просто відключається без черги невідправлених повідомлень. Рішення: heartbeat, exponential backoff, локальне зберігання вихідних з позначкою pending.
  • Offset пагінація в стрічці. При вставці нових постів користувач бачить дублі. Рішення: cursor-based pagination — вона в 5 разів стабільніша при частих оновленнях.
  • Ігнорування battery optimization на Android. ConnectionService не доживає до вхідного виклику. Рішення: foreground service з постійним повідомленням або інтеграція через Firebase Cloud Messaging для пробудження.
  • Голий WebSocket без протоколу поверх. Це винахід велосипеда. Використовуйте platform-agnostic JSON або MessagePack з type-флагом.

Стек технологій, що використовується в типовому проекті:

  • iOS: Swift 5.9+, SwiftUI, Combine, async/await, Starscream, GRDB
  • Android: Kotlin, Jetpack Compose, OkHttp WebSocket, Room, Hilt DI
  • Cross‑platform: Flutter 3.x (Dart) або React Native (TypeScript)
  • Backend: Node.js + socket.io або Phoenix (Elixir) + PostgreSQL + Redis
  • Push: APNs / FCM з сертифікатами та ключами
  • VoIP: WebRTC + coturn TURN server

⏱ Терміни орієнтовно

Модуль Оцінка
Базовий чат з історією та push 4–6 тижнів
VoIP дзвінки з CallKit / ConnectionService 3–5 тижнів
Соціальна стрічка + реакції + коментарі від 3 місяців

Вартість розраховується індивідуально після аналізу вашого технічного завдання та існуючої архітектури. Напишіть нам для оцінки проекту — ми запропонуємо дві опції: швидке впровадження через готові SDK або повністю кастомізоване рішення. Отримайте консультацію та точний кошторис протягом 2 робочих днів. Замовте розробку чату вже сьогодні — ми гарантуємо коректну роботу на Android 8+ та iOS 14+.