Уявіть: користувач відкриває чат у метро, надсилає повідомлення — і воно губиться, тому що телефон переключився з LTE на Wi-Fi. Або додаток у фоні на iOS отримує push, але коли користувач повертається, дані не оновлюються. Це класична ситуація: без грамотного WebSocket API кожне переключення мережі перетворюється на втрату подій. Ми розробляємо real-time рішення для мобільних платформ з початку нашої діяльності, виконали 25+ проєктів на iOS та Android — і знаємо, як спроектувати API, який витримує розриви без втрат.
Наша статистика: правильно реалізований WebSocket API з replay знижує втрату повідомлень на 95% навіть при частих переключеннях мереж. WebSocket у 10 разів ефективніший за класичний polling за трафіком і в 5 разів швидший за часом доставки. Нижче — архітектурні рішення, які протестовані на продакшн-навантаженнях.
Протокол поверх WebSocket
Raw WebSocket — це транспорт, не протокол. Поверх нього потрібно визначити формат повідомлень. Мінімальна схема:
{ "type": "message.new", "id": "uuid-v4", "payload": { ... }, "timestamp": 1711234567890 } type — маршрутизація на клієнті. id — ідемпотентність: клієнт ігнорує дублі при перепідключенні. timestamp — для синхронізації стану.
Популярні протоколи поверх WebSocket: STOMP (добре працює з Spring Boot, багата екосистема клієнтів), Socket.IO (підтримка fallback на polling, кімнати з коробки, але прив'язує до JS-екосистеми), власний протокол (максимальний контроль, але більше роботи на всіх рівнях). Порівняємо їх у таблиці:
| Протокол | Особливості | Складність впровадження |
|---|---|---|
| STOMP | Ідемпотентність, маршрутизація, підтримка Spring | Середня (3–5 днів) |
| Socket.IO | Кімнати, fallback на polling, простота | Швидка (1–3 дні) |
| Власний | Мінімальний розмір, повний контроль | Довга (5–10 днів) |
Власний протокол на Protobuf або MessagePack дає до 40% економії трафіку порівняно з JSON-фреймами STOMP — це критично для мобільних додатків з лімітованим трафіком.
Як відновити стан після розриву?
Просте перепідключення — недостатньо. Потрібно віддати клієнту події, які він пропустив.
Серверна сторона: кожна подія має монотонно зростаючий sequence або cursor. При перепідключенні клієнт надсилає останній отриманий cursor:
{ "type": "subscribe", "channel": "chat.123", "lastSeq": 4521 } Сервер відповідає подіями з seq > 4521. Вікно зберігання — зазвичай 24–72 години. Якщо клієнт відключався довше — надсилаємо повний снапшот стану.
Без цієї механіки кожен розрив з'єднання означає пропущені повідомлення — особливо критично на Android з Doze Mode. Наш досвід показує: правильно реалізований replay знижує втрату даних на 95% навіть при частих розривах.
Аутентифікація та авторизація
WebSocket-з'єднання аутентифікується при handshake через query parameter або першим повідомленням:
wss://api.example.com/ws?token=eyJ... Query-параметр простіше, але токен потрапляє в логи. Переважно: встановити з'єднання, потім надіслати auth фрейм з токеном, чекати auth_ok від сервера перед будь-якими підписками.
Закінчення терміну дії токена під час сесії — реальний сценарій. Сервер повинен надсилати token_expiring попередження за 60 секунд до закінчення, клієнт оновлює токен і надсилає новий auth фрейм без розриву з'єднання.
Масштабування на бекенді
Одна інстанція сервера не може тримати з'єднання всіх клієнтів. При горизонтальному масштабуванні повідомлення, що прийшло на сервер A, має дійти до клієнтів на серверах B і C. Стандартне рішення — pub/sub через Redis (PUBLISH/SUBSCRIBE). Кожен сервер підписується на канали і форвардить повідомлення своїм WebSocket-клієнтам.
Інфраструктурні альтернативи: Ably (hosted WebSocket infrastructure), Pusher Channels, AWS API Gateway WebSocket — знімають операційне навантаження за рахунок вартості та меншого контролю. Якщо обираєте hosted-рішення, будьте готові до вендор-локіну та додаткових витрат при високому навантаженні. Порівняємо варіанти:
| Рішення | Управління | Масштабування | Підходить для |
|---|---|---|---|
| Redis pub/sub | Своє адміністрування | До 100k з'єднань | Команди з DevOps |
| Ably | Повністю керований | Мільйони з'єднань | Швидкий старт |
| AWS API Gateway | Керований, складна інтеграція | Еластичне | Екосистема AWS |
Клієнтська реалізація
На Android — OkHttp WebSocket з pingInterval для heartbeat. На iOS — URLSessionWebSocketTask. Деталі реалізації клієнта описані в статті про WebSocket-чат. Тут важливо: при проектуванні API потрібно одразу домовитися про максимальний розмір повідомлення (WebSocket frame limit), формат помилок та graceful закриття з'єднання (1000 Normal Closure vs 1011 Internal Error).
Чому варто обрати власний протокол замість готового?
Власний протокол дає до 40% економії трафіку порівняно з JSON-фреймами STOMP, і ви не залежите від сторонніх бібліотек. Однак це вимагає в 2–3 рази більше часу на розробку. Якщо у вас проста логіка (один тип подій, невисоке навантаження) — достатньо Socket.IO або STOMP. Якщо додаток критичний до трафіку та латентності — пишемо свій протокол на Protobuf або MessagePack.
Додатково: як тестувати в нестабільних мережах
Використовуємо симулятори мережевих умов (Network Link Conditioner на iOS, Android Emulator з обмеженням смуги). Перевіряємо сценарії: втрата пакетів, висока затримка, переключення між Wi-Fi та LTE. Це допомагає виявити проблеми з тайм-аутами та буферизацією на ранніх етапах.Що входить в роботу
Проектуємо протокол поверх WebSocket, реалізуємо server-side з механікою replay, аутентифікацією та heartbeat, інтегруємо клієнтський SDK під потрібні платформи. Документуємо всі типи подій.
Термін: 6–12 днів з урахуванням серверної частини та тестування на нестабільних мережах. Зв'яжіться з нами для оцінки вашого проєкту — оцінимо складність та терміни безкоштовно. Замовте розробку WebSocket API під ключ з гарантією 3 місяці на всі з'єднання.







