Реализация Real-Time уведомлений через WebSocket на сайте
Представьте: пользователь оформляет заказ, но не получает уведомление об изменении статуса, пока не обновит страницу. Или модератор не видит новый комментарий до перезагрузки. Это не просто неудобство — это потеря конверсии и доверия. Мы — команда инженеров с пятилетним опытом — разрабатываем системы мгновенных уведомлений на WebSocket, которые доставляют события за миллисекунды, без лишних запросов к серверу. За 80+ проектов мы выработали надёжную архитектуру, выдерживающую пиковые нагрузки.
Почему WebSocket, а не polling?
При polling клиент каждые N секунд опрашивает сервер. При 10 000 пользователей, запрашивающих статус раз в 5 секунд, сервер получает 120 000 запросов в минуту — это огромная нагрузка и задержка до 5 секунд. WebSocket устанавливает постоянное соединение: данные поступают сразу, а трафик снижается в десятки раз. Мы используем WebSocket не только для чатов, но и для оповещений о статусах заказов, уведомлений от маркетплейсов, систем тикетов и любых задач, где нужна реактивность.
Какие проблемы решаем
Избыточный polling и нагрузка на сервер
Переход на WebSocket сокращает количество HTTP-запросов с сотен тысяч до нескольких сотен в час. На одном из проектов после замены polling на WebSocket нагрузка на backend упала на 80%, а затраты на инфраструктуру снизились в 2 раза — это экономия порядка 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 недели. Стоимость рассчитывается индивидуально — пишите, мы оценим ваш проект.







