Реалізація Real-Time сповіщень через WebSocket на сайті
Уявіть: користувач оформлює замовлення, але не отримує сповіщення про зміну статусу, доки не оновить сторінку. Або модератор не бачить новий коментар до перезавантаження. Це не просто незручність — це втрата конверсії та довіри. Ми — команда інженерів з п'ятирічним досвідом — розробляємо системи миттєвих сповіщень на WebSocket, які доставляють події за мілісекунди, без зайвих запитів до сервера. За 80+ проектів ми виробили надійну архітектуру, що витримує пікові навантаження.
Чому WebSocket, а не polling?
При polling клієнт кожні N секунд опитує сервер. При 10 000 користувачів, які запитують статус раз на 5 секунд, сервер отримує 120 000 запитів на хвилину — це величезне навантаження та затримка до 5 секунд. WebSocket встановлює постійне з'єднання: дані надходять одразу, а трафік знижується в десятки разів. Ми використовуємо WebSocket не тільки для чатів, але й для оповіщень про статуси замовлень, сповіщень від маркетплейсів, систем тікетів і будь-яких задач, де потрібна реактивність.
Які проблеми вирішуємо
Надмірний polling і навантаження на сервер
Перехід на WebSocket скорочує кількість HTTP-запитів із сотень тисяч до кількох сотень на годину. На одному з проектів після заміни polling на WebSocket навантаження на backend впало на 80%, а витрати на інфраструктуру знизилися вдвічі — це економія близько 200 000 грн на місяць.
Доставка сповіщень офлайн-користувачам
Якщо користувач закрив вкладку, але хоче отримувати сповіщення — ми зберігаємо їх в БД і надсилаємо при наступному підключенні. У нашому рішенні це реалізовано через Redis Pub/Sub з персистентністю. Додатково надсилаємо push-сповіщення через FCM/APNS. Офлайн-доставка працює із затримкою не більше 100 мс після підключення.
Масштабування для тисяч з'єднань
Один додаток може тримати десятки тисяч WebSocket-з'єднань. Ми використовуємо масштабування через Redis або Kafka, щоб з'єднання працювали на кількох інстансах. Навантажувальне тестування підтверджує стабільність до 50 000 одночасних підключень.
Як забезпечується доставка офлайн-користувачам?
У типовій архітектурі (див. код нижче) ми зберігаємо відображення userId → set<socketId>. Коли користувач підключається, ми перевіряємо наявність невідправлених сповіщень у БД і доставляємо їх. Якщо користувач офлайн — сповіщення зберігається зі статусом pending.
// notification-ws.service.ts
class NotificationWebSocketService {
private userSockets = new Map<string, Set<string>>();
async onConnect(socket: Socket, userId: string) {
if (!this.userSockets.has(userId)) {
this.userSockets.set(userId, new Set());
}
this.userSockets.get(userId)!.add(socket.id);
socket.join(`user:${userId}`);
const pending = await this.notificationRepo.findUndelivered(userId);
if (pending.length > 0) {
socket.emit('notifications:batch', pending);
await this.notificationRepo.markDelivered(pending.map(n => n.id));
}
}
async sendToUser(userId: string, notification: Notification): Promise<void> {
const isOnline = this.userSockets.has(userId) &&
this.userSockets.get(userId)!.size > 0;
if (isOnline) {
io.to(`user:${userId}`).emit('notification:new', notification);
await this.notificationRepo.markDelivered([notification.id]);
} else {
await this.notificationRepo.save({ ...notification, status: 'pending' });
await this.pushService.send(userId, notification);
}
}
}
Чому React-хук useNotifications спрощує інтеграцію?
На фронтенді ми підготували React-хук, який підписується на події socket.io. Він автоматично обробляє додавання нових сповіщень, підрахунок непрочитаних та позначку прочитаних. Все, що потрібно розробнику — викликати useNotifications() і рендерити список.
// hooks/useNotifications.ts
function useNotifications() {
const [notifications, setNotifications] = useState<Notification[]>([]);
const [unreadCount, setUnreadCount] = useState(0);
const socket = useSocket();
useEffect(() => {
if (!socket) return;
socket.on('notification:new', (notification: Notification) => {
setNotifications(prev => [notification, ...prev]);
setUnreadCount(prev => prev + 1);
showToast(notification);
});
socket.on('notifications:batch', (batch: Notification[]) => {
setNotifications(prev => [...batch, ...prev]);
setUnreadCount(prev => prev + batch.filter(n => !n.readAt).length);
});
return () => {
socket.off('notification:new');
socket.off('notifications:batch');
};
}, [socket]);
const markAsRead = async (id: string) => {
await fetch(`/api/notifications/${id}/read`, { method: 'POST' });
setNotifications(prev =>
prev.map(n => n.id === id ? { ...n, readAt: new Date() } : n)
);
setUnreadCount(prev => Math.max(0, prev - 1));
};
const markAllAsRead = async () => {
await fetch('/api/notifications/read-all', { method: 'POST' });
setNotifications(prev => prev.map(n => ({ ...n, readAt: n.readAt || new Date() })));
setUnreadCount(0);
};
return { notifications, unreadCount, markAsRead, markAllAsRead };
}
Типи сповіщень та їх візуалізація
Ми визначили типові події для типового додатку:
| Тип | Опис | Іконка |
|---|---|---|
| order:status_changed | Статус замовлення змінився | 📦 |
| message:received | Нове повідомлення в чаті | 💬 |
| mention:comment | Згадування в коментарі | @ |
| task:assigned | Призначено нове завдання | ✅ |
| payment:processed | Платіж проведено | 💳 |
| system:alert | Системне попередження | ⚠️ |
Для кожного типу можна налаштувати тривалість відображення Toast і дію при кліку.
Порівняння polling і WebSocket
| Параметр | Polling | WebSocket |
|---|---|---|
| Затримка | 1–5 сек | < 100 мс |
| Навантаження на сервер | Висока | Низька |
| Трафік | ~120 000 запитів/хв | ~1 000 повідомлень/хв |
| Масштабування | Складно при великій кількості клієнтів | Легко з Redis/Kafka |
Що входить у роботу
- Архітектурна документація: опис схеми взаємодії, вибір стеку (Socket.IO, Redis, PostgreSQL).
- Реалізація backend-сервісу: WebSocket handler, інтеграція з системою авторизації, обробка відключень.
- Frontend-модуль: React-хук, компонент дзвіночка, Toast-сповіщення.
- Інтеграція з push-сповіщеннями (FCM/APNS) — за бажанням.
- Навантажувальне тестування: перевірка до 50 000 одночасних з'єднань.
- Інструкція з розгортання та навчання команди.
Ми гарантуємо стабільну роботу системи при пікових навантаженнях — досвід 5+ років у розробці real-time рішень і 80+ виконаних проектів говорять самі за себе. Зв'яжіться з нами, щоб обговорити ваш проект — ми допоможемо обрати оптимальну архітектуру та реалізуємо під ключ. Отримайте консультацію прямо зараз.
Процес роботи
- Аналітика — вивчаємо поточну архітектуру, визначаємо сценарії сповіщень, навантаження.
- Проектування — обираємо протокол (WebSocket, SSE), брокер повідомлень (Redis, Kafka), схему зберігання.
- Реалізація — пишемо backend + frontend, покриваємо тестами.
- Інтеграція — приєднуємо до існуючого проекту (Laravel, Nest.js, Django та ін.).
- Деплой і моніторинг — налаштовуємо CI/CD, логування, алерти.
Терміни орієнтовно
Базова реалізація (WebSocket + React + зберігання офлайн) — 7–10 днів. З інтеграцією push-сповіщень і навантажувальним тестуванням — 2–3 тижні. Вартість розраховується індивідуально — пишіть, ми оцінимо ваш проект.







