WebSocket vs SSE vs Long PollingWebSocket против SSE и long polling
Three ways to get fresh dataТри способа получать свежие данные
“Real-time” is not one technology. Before reaching for WebSocket, it's worth knowing the two alternatives — because for many apps a simpler transport is the right call.
- Long polling — the client makes a request the server holds open until it has data, then immediately re-requests. Works everywhere; awkward and chatty.
- Server-Sent Events (SSE) — a one-way stream of text events over a single HTTP response, with automatic reconnection built into the browser's
EventSource. - WebSocket — a full-duplex binary-capable channel after an HTTP upgrade.
«Реальное время» — это не одна технология. Прежде чем хвататься за WebSocket, стоит знать два альтернативных подхода — для многих приложений более простой транспорт оказывается правильным выбором.
- Long polling — клиент шлёт запрос, который сервер держит открытым до появления данных, затем сразу запрашивает снова. Работает везде; неуклюже и «болтливо».
- Server-Sent Events (SSE) — односторонний поток текстовых событий поверх одного HTTP-ответа, с автоматическим переподключением, встроенным в браузерный
EventSource. - WebSocket — полнодуплексный канал с поддержкой бинарных данных после HTTP-upgrade.
Side by sideСравнение
| WebSocket | SSE | Long polling | |
|---|---|---|---|
| Direction | Full-duplex | Server → client only | Half-duplex (per request) |
| Binary payloads | Yes | No (text/UTF-8) | Yes (as HTTP body) |
| Auto-reconnect | Manual | Built in | Inherent |
| Browser API | WebSocket | EventSource | fetch/XHR |
| Works over plain HTTP/2 | Needs upgrade | Yes | Yes |
| Overhead per message | Very low | Low | High (full request) |
| Best for | Chat, games, collab | Feeds, notifications | Legacy / fallback |
| WebSocket | SSE | Long polling | |
|---|---|---|---|
| Направление | Полный дуплекс | Только сервер → клиент | Полудуплекс (на запрос) |
| Бинарные данные | Да | Нет (текст/UTF-8) | Да (тело HTTP) |
| Авто-переподключение | Вручную | Встроено | По природе |
| Браузерный API | WebSocket | EventSource | fetch/XHR |
| Поверх обычного HTTP/2 | Нужен upgrade | Да | Да |
| Накладные на сообщение | Очень низкие | Низкие | Высокие (полный запрос) |
| Лучше для | Чаты, игры, совместная работа | Ленты, уведомления | Легаси / фолбэк |
SSE in five linesSSE в пять строк
If you only push from the server — a price ticker, a notification feed, build logs — SSE is dramatically simpler and free of the reconnection code WebSocket demands:
const es = new EventSource("/api/stream"); es.onmessage = (e) => console.log("event:", e.data); es.onerror = () => console.log("reconnecting…"); // browser retries for you
Если вы только отправляете данные от сервера — биржевой тикер, лента уведомлений, логи сборки — SSE значительно проще и избавляет от кода переподключения, который требует WebSocket:
const es = new EventSource("/api/stream"); es.onmessage = (e) => console.log("event:", e.data); es.onerror = () => console.log("reconnecting…"); // браузер переподключается сам
How to chooseКак выбрать
Reach for SSE when data flows one way and is text. Reach for WebSocket when the client also sends frequently, when you need binary frames, or when latency in both directions matters. Keep long polling only as a fallback for environments that block the other two. Many production stacks layer all three behind a single client API and negotiate the best available transport at connect time.
Берите SSE, когда данные текут в одну сторону и это текст. Берите WebSocket, когда клиент тоже часто отправляет, нужны бинарные кадры или важна задержка в обе стороны. Оставьте long polling только как фолбэк для окружений, где первые два заблокированы. Многие продакшен-стеки прячут все три за единым клиентским API и выбирают лучший доступный транспорт при подключении.