25 августа 2026 г.
Интерфейс на SSE+Fetch врёт до перезагрузки: ответ и событие приходят в разном порядке
Жозе Валим предлагает мерить не латентность, а корректность: сам по себе такой рассинхрон не сойдётся никогда.

José Valim
@josevalim
Новый пост! Спор о WebSockets против SSE должен идти о порядке событий и корректности: https://dashbit.co/blog/websockets-vs-sse С SSE+Fetch очень легко получить и отрисовать события в неверном порядке. Дальше пользователь либо путается, либо принимает решение по неверным данным. В статье много диаграмм, которые показывают проблемы разных подходов. Статью целиком написал человек, а вычитали LLM. Интерактивные примеры целиком сделал код-агент под присмотром взрослых.

Один пользователь добавляет тег «elixir», второй в ту же секунду удаляет «javascript». На экране остаётся список, которого нет ни у кого.
Так ломается связка SSE+Fetch. Жозе Валим разобрал этот сбой 25 августа в блоге Dashbit, в посте «WebSockets vs. SSE should be about ordering and correctness». Ответ на действие приходит по Fetch, событие рассылки идёт по SSE, а сеть, сборщик мусора или прокси легко меняют их местами.
Частный баг Валим поднимает до правила выбора: спорить о WebSockets и SSE надо не про латентность и размер передаваемых данных, а про порядок событий и корректность.
Почему это не «просто eventual consistency»
Само не сойдётся. Обычный ответ на такую жалобу: система же eventually consistent, данные догонят. Валим отбивает: «eventually consistent система гарантирует, что при отсутствии новых апдейтов все копии данных сойдутся к одному значению. Здесь этого не произойдёт». Неверный список висит, пока читатель не перезагрузит страницу.
Раньше спорили про скорость. В треде Hacker News про HTML over WebSockets советовали брать SSE и встроенный Fetch вместо самописного клиента: браузеры мультиплексируют HTTP-запросы поверх одного TCP-соединения, поэтому латентность выходит та же. Со скоростью Валим не спорит. Он говорит, что мерили не то.
Что делать, если WebSockets не вариант
У WebSockets канал один и двунаправленный, поэтому порядок между операциями клиента и ответами на них сохраняется дёшево, без прогона своих операций через отдельный путь доставки. Побочный счёт тоже в их пользу. При SSE+Fetch каждый запрос заново расшифровывает сессию и достаёт пользователя из базы или кэша, а WebSocket-соединение аутентифицируется один раз и держит данные пользователя в памяти.
Первоисточник