A few additional cons to be aware of:<p>WebSockets lack flow control (backpressure) and multiplexing, so if you need them you either roll your own or use something similar to RSocket.<p>Also SSE can't send binary data directly. You have to base64 encode it or similar.<p>WebTransport addresses these and also solves head of line blocking. But I'm concerned that we might run into a similar problem as we had with going from Python2 to Python3 and IPv6. Too easy for people to keep using the old version, and too little (perceived) benefit to upgrading.<p>As long as browsers still work with TCP, some networks will continue to block UDP (and thus HTTP3/WebTransport) outright.
The article's information about WebRTC is not accurate. You can do client/server WebRTC without a "signaling server". Just make the server do the signaling. It takes a few extra round trips, but it doesn't need to be an extra server. And WebRTC data channels work quite well as a replacement for WebSockets or SSE, especially if you want to avoid head-of-line blocking. And there are many libraries that will do pretty much all of the work for you, like Pion or str0m.<p>I also think calling the WebTransport API complex is overblown. If you don't want the more advanced things, you can ignore them. If you want to use it like a WebSocket, just open one bidirectional stream and you're basically done. If you want to avoid head-of-line blocking, just open a stream for every message. It's a little more complex, but it's not the kind of thing you need a library for. Github Copilot will probably write the code for you. It's true there aren't as many server libraries out there yet, since WebTransport is still maturing. And we're waiting for Safari to add support.
Or, if you’re building for clients with a traditional “enterprise” and “secure” IT infrastructure: add refresh buttons and call it a day.
If there’s one thing in my experience that consistently fails in these environments and cannot be fixed due to endless red tape, it’s trying to make real-time work for these type of clients.
websockets and sse are a big headache to manage at scale, especially backend, requires special observability, if not implemented really carefully on mobile devices its a nightmare to debug on frontend side<p>devices switch off network or slow down etc,... for battery conservation, or when you don't explicitly do the I/O using a dedicated API for it.<p>new connection setup is a costly operation, the server has to store the state somewhere and when this stateful layer faces any issue, clients keep retrying and timing out. forever stuck on performing this costly operation. it's not like there is an easy way to control the throughput and slowly put the load on database<p>reliability wise long polling is the best one IME, if event based flow is really important, even then its better to have a 2 layer backend, where frontend does long polling on the 1st layer which then subscribes to websockets to the 2nd layer backend. much better control in terms of reliability
Not in the article by also relevant is short polling. While this does not send messages from a server to a client it can still be useful when all other options are not available (on shared hosting for example).<p>In my experience it even works great when the poll interval is long (for example 20 seconds) but when you also include the message list in each response. That way the client will be up to date when it interacts with the server: user presses a button -> the client sends a request to the server -> the server reponds with data and also a list of the latest messages.
To this day I still dont know why WebSockets and SSE dont support sending headers on the initial request, such as Authorization. Leaving authentication on realtime services entirely up to whoever is implementing the service.<p>I may be wrong here and the spec suggests a good way to do it, but i've seen so many different approaches that at this point might as well say there's none.
This is probably naive, but it seems like assuming HTTP/2 or better, an EventSource combined with fetch() for sending messages should be just as good as any other protocol that uses a single TCP connection? And HTTP/3 uses UDP, so even better.<p>(This all assumes you only care about maintaining a connection when the tab is in the foreground.)<p>I’m wondering what problems people have run into when they tried this.
I always find articles like this amusing, because I designed an online auction system back in the late 90's. No XHR requests at all. Real-time updates were all handled with server-push/HTTP streaming. It wasn't easy to handle all the open connections at the time, but it could be done to an acceptable scale with the right architecture.
I kind of miss long polling. It was so stupidly simple compared to newer tech, and that's coming from someone who thinks WebRTC is the best thing since sliced bread.
Jsonrpc over websockets is underrated tech. Simple, easy to implement, maps to programming language constructs (async functions, events, errors) which means code looks natural as any library/package/module usage devs are used to, can be easily decorated with type safety, easy to debug, log, optimize etc, works on current browsers and can be used for internal service to service comms, it's fast (ie. nodejs is using simdjson [0]), can be compressed if needed (rarely the need), we built several things on top of it ie. async generators (avoids head of line blocking, maps naturally to typescript/js async generators).<p>[0] <a href="https://github.com/simdjson/simdjson">https://github.com/simdjson/simdjson</a>
(I work at Stream, we power activity feeds, chat and video calling/streaming for some very large apps)<p>You should in most cases just use websockets with a keep-alive ping every 30 seconds or so. It's not common anymore to block websockets on firewalls, so fallback solutions like Faye/Socket.io are typically not needed anymore.<p>WebTransport can have lower latency. If you're sending voice data (outside of regular webrtc), or have a realtime game its something to consider.
A decent number of corporate firewalls still don't support web sockets...<p>That means if you build something that requires web sockets, prepare to have a deluge of support/refund requests from the most valuable clients who think your site is broken.<p>I suggest just having a once-per-second polling fallback, perhaps with an info bar saying 'the network you are connected to is degrading your experience'.
Hello, I am author of <a href="https://github.com/centrifugal/centrifugo">https://github.com/centrifugal/centrifugo</a>. Our users can choose from WebSocket, EventSource, WebTransport (experimental for now, but will definitely stabilize in the future). WebRTC is out of scope as the main purpose is central server based real-time json/binary messaging, and WebRTC makes things much more complex since it shines for peer-to-peer and rich media communications.<p>What I'd like to add is that Centrifugo also supports HTTP-streaming – not mentioned by the OP – but this is a transport which has advantages over Eventsource - like possibility to send POST body on initial request from web browser (with SSE you can not), it supports binary, and with Readable Streams browser API it's widely supported by modern browsers.<p>Another thing I'd like to mention about Centrifugo - it supports bidirectional WebSocket fallbacks with EventSource and HTTP-streaming, and does this without sticky sessions requirement in distributed scenario. I guess nobody else have this at this point. See <a href="https://centrifugal.dev/blog/2022/07/19/centrifugo-v4-released#modern-websocket-emulation-in-javascript" rel="nofollow">https://centrifugal.dev/blog/2022/07/19/centrifugo-v4-releas...</a>. Which solves one more practical concern. Sticky sessions is an optimization in Centrifugo case, not a requirement.<p>If you are interested in topic, we also have a post about WebSocket scalability - <a href="https://centrifugal.dev/blog/2020/11/12/scaling-websocket" rel="nofollow">https://centrifugal.dev/blog/2020/11/12/scaling-websocket</a> - it covers some design decisions made in Centrifugo.
I've been reading about WebRTC, does anyone actually know if browser to browser communication actually works reliably in practice ? Specifically NAT traversal, been hesitant to research it further because of this issue, seems that most of the connection parts seem to be legacy voip related protocols.
Is there a modern open-source solution for bridging a traditional stateless web application to real-time notifications - one that's implemented all the best practices from the OP? Something like pusher.com but on self-hosted infrastructure/k8s, where messages from clients are turned into webhooks to an arbitrary server, and the server can HTTP POST to a public/private channel that clients can subscribe to if they know the channel secret.<p>I've come across <a href="https://github.com/soketi/soketi">https://github.com/soketi/soketi</a> and <a href="https://centrifugal.dev/" rel="nofollow">https://centrifugal.dev/</a> but not sure if there are more battle-tested solutions.
Great comparison. Would love to see http response streaming added to the mix. I think a lot of use cases involving finite streams sent from server to client can be handled by the server streaming JSONL in the response. I tend to prefer this over SSE for finite data streams.
HTTP (POST) AJAX calls + SSE is one of the simplest ways to implement bi-directional real time functionality. IMHO this is a much more robust and nicer way than web sockets for a huge amount of applications which use web sockets today.
I did some testing with using SSE to send push notifications to my phone if someone set off a sensor, worked kinda good, but the browser had to be running in the background in order for it to work. After that i implemented a chat for a meme app that I've created to share memes with my friends, using websocket (Open Swoole) it is working nicely also. Never tested to see how many clients it can handle at once, but i guess the bottleneck would be in my server, not the software.<p>Open Swoole is very easy to setup and there's lots of tutorials online. Got my ass kicked a little bit trying to making my websocket secure (wss) but I'm the end it worked fine.
Browser push APIs are hard to design well regardless of the underlying protocol (SSE, Long Polling, Websockets, etc). There are a bunch of things to consider:<p>- Is this a full or partial state update?<p>- What if the client misses an update?<p>- What if the client loses connectivity?<p>- How can the server detect and clean up clients that have disappeared?<p>How those are answered in turn raise more questions.<p>SSE or long polling or even WebSockets is a relatively unimportant implementation detail. IMO the bigger consideration should probably be ease-of-use and tooling interoperability. For that, I would say that long polling (or even just <i>polling</i>) is the clear winner.
What I want to know is, on iOS can we have Web Workers running for a few hours when the browser is in the background, with setInterval communicating w the network or will they get suspended?
Never had a good experience with anything using Server-Sent-Events, this especially goes for TFS, open a tab too many and all your TFS tabs just freeze
> Long-Polling: The least scalable due to the high server load generated by frequent connection establishment, making it suitable only as a fallback mechanism.<p>That makes no sense. Long-polling scales linearly like all the other ones as well.
Man... I was trying to use WebRTC over ten years ago to implement livestreaming from your phone's camera *within a PhoneGap app*! Didn't work too well.
Note that the author misses an essential point: custom compression dictionaries, which can only be used by WebSockets (WS13) and hardly by the others, as that would break compatibility. I'd argue that you can push websocket data usage way lower than the other protocols, if you use a binary compression based on a predefined schema.<p>In WebSockets, you can use plug&play extensions which can modify the payload on both the client and the server, which make them also ideal for tunneling and peer-to-peer applications.<p>I've written an article from an implementer's perspective a while ago, in case you are interested [1]<p>[1] <a href="https://cookie.engineer/weblog/articles/implementers-guide-to-websockets.html" rel="nofollow">https://cookie.engineer/weblog/articles/implementers-guide-t...</a>