16 ms·
You might not need WebSockets
- givemeethekeys 1y ago> It makes your server code more complex. And, that is why we have frameworks to at least in the case of Web Sockets, make things as easy as regular old REST.
- Dwedit 1y agoWebSockets can't go through proxies.
- kingforaday 1y agoI think what you are getting at is that websockets aren't as simple as http traffic through a proxy, but you absolutely can use proxies and ws connections just fine and for a variety of reasons.
- Austizzle 1y agoI've definitely used websockets through nginx
- hombre_fatal 1y agoThey even go through Cloudflare.
- pier25 1y agoor Fly.io
- paxys 1y agoSays who?
- bastawhiz 1y agoThis isn't based on any facts
- andrewmcwatters 1y agohttps://nginx.org/en/docs/http/websocket.html https://nginx.org/en/docs/http/websocket.html
- mad_vill 1y agoFor all the other comments, parent is probably talking about forward proxies and to their point many forward/enterprise proxies have configurations which cause websockets to break and it is a pain to debug this if you have many enterprise customers.
- mappu 1y agoEchoing this. At $DAYJOB some 5-10% of customers will fail to initiate a websocket connection, even over wss:// despite plain HTTPS requests working fine. This is a client-side issue with whatever outdated HTTP CONNECT implementation the enterprise has.
- gregors 1y agoWorks completely fine in Haproxy
- shadowangel 1y agoI use them though nginx/cloudflare. they work fine.
- xiphias2 1y agoWith HTTP streaming the browser shows that it's still loading data. Is there some mitigation for it after the initial loading?
- panic 1y agoI'm guessing you would use JS to fetch() the stream resource separately.
- bob1029 1y agoThe fetch API is asynchronous. The initial page load would deliver the payload that then initiates the streaming connection in the background.
- lxgr 1y agoThat sounds less like a problem with HTTP streaming (initiated from JavaScript) and more like a page with some hanging resource.
- almosthere 1y agoI liked vert.x's strategy of seamlessly downgrading the form of connection based on what is available.
- winrid 1y agoVert.x is great! I'm missing it lately with Node. At least with Vert.x you get a stack trace when you block the event loop by accident...
- ramesh31 1y agoYou probably do. Reliable SSE is a complete nightmare.
- deleted 1y ago[deleted]
- koakuma-chan 1y agoWhy?
- deleted 1y ago[deleted]
- albuic 1y agoCan you explain ?
- notpushkin 1y ago> Bonus: Making it easy with eventkit Why not just use SSE? https://developer.mozilla.org/en-US/docs/Web/API/Server-sent_events/Using_server-sent_events https://developer.mozilla.org/en-US/docs/Web/API/Server-sent...
- osigurdson 1y agoBased on my read, this basically is SSE but doesn't use the same protocol.
- kordlessagain 1y agoSSE is the way to roll.
- gorjusborg 1y agoThe problem selects the solution. That said, I like SSE for unidirectional string-encoded events.
- supahfly_remix 1y agoDo CDN, such as Cloudflare, support SSE? The last time I looked, they didn't, but maybe things have changed.
- bastawhiz 1y agoYes, they are
- hntrl 1y agoI have a demo of this for CF workers https://github.com/hntrl/eventkit/tree/main/examples/workers-chat-demo https://github.com/hntrl/eventkit/tree/main/examples/workers... (it's not SSE in particular, but it demonstrates that you can have a long running stream like SSE)
- nyrikki 1y agoCloudflare doesn't officially support SSE, but if you send keepalives events every 15 or 20sec or so you can reliably use SSE for 40 min + in my experiance. No server traffic for 100+ sec officially results in a 524, so you could possibly make that keepalive interval longer, but I haven't tested it. Make sure to have the new style cache rule with Bypass cache selected and absolutely make sure you are using HTTP/2 all the way to the origin. The 6 connections per browser limit of HTTP/1.1 SSE was painful, and I am pretty sure auto negotiation breaks, often in unexpected ways with a HTTP/1.1 origin.
- colesantiago 1y agoOne thing I couldn’t get working with websockets is how do you keep websocket connections active during code deployments without disconnecting current connected clients? Sounds very tricky to me to get right even at scale.
- paxys 1y agoThe trick is to make the connection stateless, i.e. any client can connect to any server (just like plain HTTP). Then when there's a new deployment the websocket connection will be terminated and the client can reconnect instantly, automatically finding the next available server.
- hombre_fatal 1y agoIt's a minor point in the article, but sending a RequestID to the server so that you get request/response cycles isn't weird nor beyond the pale. It's pretty much always worth it to have an API like `send(message).then(res => ...)` in a serious app. But I agree. The upgrade request is confusing, and it's annoying how your websocket server is this embedded thing running inside your http server that never integrates cleanly. Like instead of just reusing your middleware that reads headers['authorization'] from the websocket request, you access this weird `connectionParams` object that you pretend are request headers, heh. But the idiosyncrasies aren't that big of a deal (ok, I've just gotten used to them). And the websocket browser API is nicer to work with than, say, EventSource.
- syspec 1y agoIt's a good well worn tactic. You list in very high detail every single step of any process you don't like. It makes that process seem overly complex, then you can present your alternative and it sounds way simpler. For example, making a sandwich: You have to retrieve exactly two slices of bread after finding the loaf in the fridge. Apply butter uniformly after finding the appropriate knife, be sure to apply about a 2.1mm level of coating. After all of that you will still need to ensure you've calibrated the toaster!"
- deleted 1y ago[deleted]
- jongjong 1y agoPretty much. In this case, WebSockets is simpler to implement than HTTP2; it's closer to raw TCP, you just send and receive raw packets... It's objectively simpler, more efficient and more flexible. It's a tough sell to convince me that a protocol which was designed primarily for resource transfer via a strict, stateless request-response mode of interaction, with server push tacked on top as an afterthought is simpler than something which was built from the ground up to be bidirectional.
- bobmcnamara 1y ago
- DadBase 1y agoMy HTTP streaming has slowed to more of a trickle the last couple of years.
- theteapot 1y agoReads like a series of strawman arguments if you replace "WebSockets" with socket.io. - "messages aren’t transactional": You can process request and return a value to sender in socket.io application layer. Is that transactional enough? - "If you’re sending messages that don’t necessarily need to be acknowledged (like a heartbeat or keyboard inputs), then Websockets make a great fit". But socket.io has acknowledgements. - "When a new WebSocket connection is initiated, your server has to handle the HTTP “upgrade” request handshake.". You can bypass handshake and go straight to WS even in Websockets, and if you don't socket.io handles upgrade for you pretty nicely so you not parsing HTTP header ..
- hntrl 1y agoIt's a good thing I didn't then :shrug: Websockets are a web standard, socket.io is a userland framework
- theteapot 1y agoIt's like arguing web components suck because there is all these problems you need to solve, while pretending web component frameworks (React, Vue, Angular, ..) that solve all those problems don't exist.
- osigurdson 1y ago>> If it wasn’t, we couldn’t stream video without loading the entire file first I don't believe this is correct. To my knowledge, video stream requests chunks by range and is largely client controlled. It isn't a single, long lived http connection.
- dangoodmanUT 1y agoCorrect
- deleted 1y ago[deleted]
- EE84M3i 1y agoI believe that's standard for Netflix, etc, but is it also true for plain webms and mp4s in a <video> tags? I thought those were downloaded in one request but had enough metadata at the beginning to allow playback to start before the file is completely downloaded.
- wewewedxfgdf 1y agoYes it is true. Browsers talking to static web servers use HTTP byte ranges requests to get chunks of videos and can use the same mechanism to seek to any point in the file. Streaming that way is fast and simple. No fancy technology required. For MP4 to work that we you need to render it as fragmented MP4.
- jofla_net 1y agoSeconded, ive done a userland 'content-range' implementation myself. of course there were a few ffmpeg specific parameters the mp4 needed to work right still
- EE84M3i 1y agoWhy would the browser send byte range requests for video tags if it expects to play the file back linearly from beginning to end anyway? Wouldn't that be additional overhead/round-trips?
- wewewedxfgdf 1y agoI wrote a subsystem the other day that used websockets for a server to distribute video conversion tasks. After futzing with silly things like file transfers and communication protocols I chucked it out and rewrote it so the client does HTTP long polling of the server and uploads its renders via hTTP POST. So much easier.
- ricardobeat 1y agoThat used to be called “Comet” back in the early 2000s. Did you try using an established library like socket.io, connectRPC etc? They handle a lot of the complexity.
- wewewedxfgdf 1y agoLong polling is easy - all it means is your server does not immediately respond - nothing more to it than that.
- ricardobeat 1y agoNot really the case for user-facing applications. Proxies can time out, detecting stalls is hard, reconnection is expensive, TCP slow start means higher latency, the overhead is huge for small messages. Implementing it properly is not trivial, the WebSocket standard was created precisely to improve on those shortcomings. Good for you that it works for your case, though if all you need is to listen to a stream you might also be better served by SSE. I was asking since Socket.io, for example, takes care of file uploads, reconnection, the whole HTTP upgrade flow, and is extremely easy to use, both on client and server. On top of that it can fall back to long-polling if WS is not available. Here's a link for educational purposes: https://en.wikipedia.org/wiki/Comet_(programming) https://en.wikipedia.org/wiki/Comet_(programming)
- noduerme 1y agoLong polling is great for most things that don't need a realtime push. It just gets to be a strain on a server if you've got to set up and tear down lots of those connections from lots of users. Keeping a socket alive is a lot less resource intensive. Maybe it sounds stupid, but I've even converted PHP code that responded to long polling to handle the same polling over a socket to save resources. Most of my apps that need some kind of lazy updates actually work this way, and fall back to REST polling the same services if the socket is down.
- RajT88 1y agoThe world needs more of these "you might not need" articles. Too many technology fads make things needlessly complicated, and complexity makes systems unreliable. You might not need Kubernetes You might not need The Cloud You might not need more than SQLite ...and so on.
- morsecodist 1y agoGenuine question because I agree that there are a lot of over complicated systems. I often see people say all you need is SQLite. Do you implement replication yourself? Or you are just accepting that if something happens to your server your data is just gone? I always default to managed Postgres and that seems to be the simplest most boring solution.
- DrFalkyn 1y agoReplication in SQLLite cp data.db <backuo location> On modern cloud systems you shouldn’t have data loss anyway
- JSR_FDED 1y agoThere's a huge class of applications for which Litestream provides all the replication of SQLite databases you need. https://litestream.io https://litestream.io https://github.com/benbjohnson/litestream https://github.com/benbjohnson/litestream
- immibis 1y agoSQLite is absolutely not suitable if you need non-trivial amounts of write concurrency - SQLite locks the file when writing, and doesn't even notify the next writer when done - writers poll to see if it's unlocked yet. If you don't use WAL mode, then readers have to wait for writers to. You can still back up your SQLite database file. You shouldn't do it in the middle of a write, or you should use the SQLite backup API to manage concurrency for you, or you can back it up in SQL dump format. This isn't one of the usual reasons you shouldn't use SQLite. If you need synchronous replication, then you shouldn't use SQLite. SQLite is robust against process crashes and even operating system crashes if fsync works as it should (big if, if your data is important), but not against disk failure. In most of the cases when you shouldn't use SQLite, you should still just upgrade one step to Postgres, not some random NoSQL thing or Google-scale thing.
- socketcluster 1y agoThe problem with HTTP2 is that the server-push aspect was tacked on top of an existing protocol as an afterthought. Also, because HTTP is a resource transfer protocol, it adds a whole bunch of overheads like request and response headings which aren't always necessary but add to processing time. The primary purpose of HTTP2 was to allow servers to preemptively push files/resources to clients to avoid round-trip latency; to reduce the reliance on script bundles. WebSockets is a simpler protocol built from the ground up for bidirectional communication. It provides a lot more control over the flow of data as everything passes over a single connection which has a single lifecycle. It makes it a lot easier to manage state and to recover cleanly from a lost connection when you only have one logical connection. It makes it easier to process messages in a specific order and to do serial processing of messages. Having just one connection also greatly simplifies things in terms of authentication and access control. I considered the possibility of switching the transport to HTTP2 for https://socketcluster.io/ https://socketcluster.io/ years ago, but it's a fundamentally more complex protocol which adds unnecessary overheads and introduces new security challenges so it wasn't worth it.
- koakuma-chan 1y agoHow can server push be a problem with HTTP/2 if nobody supports server push? It's dead. And what about multiplexing and header compression? Not worth it?
- mountainriver 1y agoAgree after banging my head against http2 for years, I now really enjoy how simple websockets are and their universal support
- tsimionescu 1y agoServer push is dead though, SSE is a different idea with completely different semantics (and tradeoffs).
- alt227 1y ago> The primary purpose of HTTP2 was to allow servers to preemptively push files/resources to clients to avoid round-trip latency; to reduce the reliance on script bundles. The primary purpose for HTTP2 was to allow multiple simultaneous asynchoronous http calls, which is a massive loading performance boost for most websites. Server push was very much a tacked on afterthought.
- QuarterDuplex 1y agojust use meteor.js https://www.meteor.com/ https://www.meteor.com/ ?
- bmitc 1y agoI personally view WebSockets as a nicer TCP that has all the messaging functionality you end up building anyway than as an alternative to HTTP.
- collingreen 1y agoOof, what a headline to be top of hn the day after you implement websockets into a project.
- sampullman 1y agoWebsockets work great, don't worry too much about it.
- bonestamp2 1y agoWe've had a production app with them for over 10 years and it's generally great. The only thing to be aware of is this Chrome bug: https://issuetracker.google.com/issues/362210027?pli=1 https://issuetracker.google.com/issues/362210027?pli=1 You can add a recurring ping/pong between the client/server so you can know with some recency that the connection has been lost. You shouldn't have to do that, but you probably want to until this bug is fixed.
- philipwhiuk 1y ago60s heartbeat interval, job done. We've got multiple internal apps using WebSockets in production, for years. I have to say I don't really get all the concern in the article about upgrading the connection - any decent backend framework should handle this for you without a problem. Hacker News articles on new libraries generally live in the 1% of the 1%. For lots of websites, they don't need a web-socket because they are just doing CRUD. For the 1% doing live updates, web-sockets are great and straight-forward. For whatever specialised use case the article has, sure there's something even less well supported you can pivot to.
- bonestamp2 1y agoWe use a much short heartbeat interval because our use case is for real time control and monitoring so our users need to know immediately if the connection is lost.
- sneilan1 1y agoWhy do you need to implement your own web socket server? Why not use AWS appsync events?
- dgfitz 1y agoI think at this point in my career my goal is to continue to never, ever, work on a public-facing website. 20 years into this foray of a career and I’ve avoided it so far.
- shusson 1y agoThe article forgot to mention websockets add state to the server! Load balancing will require sticking sessions. At scale this tends to mean separating websocket servers completely from http servers.
- toomim 1y agoPeople interested in HTTP streaming should check out Braid-HTTP: https://braid.org https://braid.org. It adds a standard set of semantics that elegantly extend HTTP with event streaming into a robust state synchronization protocol.
- efortis 1y agoYou can also use long polling, which keeps alive a connection so the server can respond immediately when there’s new data. For example: Server const LONG_POLL_SERVER_TIMEOUT = 8_000 function longPollHandler(req, response) { // e.g. client can be out of sync if the browser tab was hidden while a new event was triggered const clientIsOutOfSync = parseInt(req.headers.last_received_event, 10) !== myEvents.count if (clientIsOutOfSync) { sendJSON(response, myEvents.count) return } function onMyEvent() { myEvents.unsubscribe(onMyEvent) sendJSON(response, myEvents.count) } response.setTimeout(LONG_POLL_SERVER_TIMEOUT, onMyEvent) req.on('error', () => { myEvents.unsubscribe(onMyEvent) response.destroy() }) myEvents.subscribe(onMyEvent) } Client (polls when tab is visible) pollMyEvents() document.addEventListener('visibilitychange', () => { if (!document.hidden) pollMyEvents() }) pollMyEvents.isPolling = false pollMyEvents.oldCount = 0 async function pollMyEvents() { if (pollMyEvents.isPolling || document.hidden) return try { pollMyEvents.isPolling = true const response = await fetch('/api/my-events', { signal: AbortSignal.timeout(LONG_POLL_SERVER_TIMEOUT + 1000), headers: { last_received_event: pollMyEvents.oldCount } }) if (response.ok) { const nMyEvents = await response.json() if (pollMyEvents.oldCount !== nMyEvents) { // because it could be < or > pollMyEvents.oldCount = nMyEvents setUIState('eventsCount', nMyEvents) } pollMyEvents.isPolling = false pollMyEvents() } else throw response.status } catch (_) { pollMyEvents.isPolling = false setTimeout(pollMyEvents, 5000) } } Working example at Mockaton: https://github.com/ericfortis/mockaton/blob/6b7f8eb5fe9d3baf95463828a11959b8615b7805/src/Api.js#L79 https://github.com/ericfortis/mockaton/blob/6b7f8eb5fe9d3baf...
- hattmall 1y agoYep, have used long polling with no downsides for ~20 years. 95% of the time I see web sockets it's unnecessary.
- oneoverten 1y agoWhat does this solve? Genuine question. You still have to manage connectivity, and synchronization. Also not so sure that stream reading will necessarily be quantized chunks of your updates sent from the server.
- djfobbz 1y agoWe have multiple mission-critical, industrial-grade WebSocket monitoring applications that have been running rock-solid for the last eight years without any hiccups in manufacturing environments. It seems like you're taking an easy-to-maintain codebase and turning it into a complex monstrosity.
- lxgr 1y ago> We can’t reliably say “the next message” received on the stream is the result of the previous command since the server could have sent any number of messages in between now and then. Doing so is a protocol decision though, isn't it? If the protocol specifies that the server either clearly identifies responses as such, or only ever sends responses, and further doesn't send responses out of order, I don't see any difference to pipelined HTTP: The client just has to count, nothing more. (Then again, if that's the use case, long-lived HTTP connections would do the trick just as well.)
- scheme271 1y agoWhat happens if a message somehow gets lost? Dropped packets, error, etc? Or is that completely precluded by using http streaming?
- lxgr 1y agoTCP provides a lossless in-order stream, and errors are corrected at the layers even below that, so HTTP and WebSockets are equivalent in that regard.
- suzzer99 1y agoMe: For this POC you've given me, I will do an old-fashioned HTTP form submit, no need for anything else. Architect: But it must have websockets! Me: Literally nothing in this POC needs XHR, much less websockets. It's a sequential buy flow with nothing else going on. Architect: But it has to have websockets, I put them on the slide! (Ok he didn't say the part about putting it on the slide, but it was pretty obvious that's what happened. Ultimately I caved of course and gave him completely unnecessary websockets.)
- deleted 1y ago[deleted]
- ticoombs 1y agoI always try and push back on those beliefs, about reasonings why they believe it will be faster or more efficient than some other solution. I've found , if you could type cast those people, they would be a tech architect who only uses "web scale" items. (Relevant link: https://www.youtube.com/watch?v=5GpOfwbFRcs https://www.youtube.com/watch?v=5GpOfwbFRcs )
- suzzer99 1y agoI call them Powerpoint architects.
- kigiri 1y agoMy strategy for this kind of situation is to avoid direct rejection. Instead of saying stuff like "it's unnescessary" or "you are wrong", I push for trying first without. I would say: > Once we have a working MVP without websockets we can talk again to think about using websocket. Most times, once something is working, they then stop to care, or we have other priorities then.
- syntaxing 1y agoMaybe I'm naive? But I thought its if you need stateful, use websockets. Else, use short/long poll or SSE.
- Spivak 1y agoDiscord and Slack do the article's suggestion of using web sockets for the receiving side only (mostly) and having you switch to http on the calling side. It works pretty well, you have to keep two sets of books but the web socket side is almost always for events that you, the client, should be responding to so it works somewhat like a reverse http but that works with your firewall. It also allows Discord to implement trivial, from the client's perspective, sharding. It really is clever as hell, scaling up a bot/integration is as easy as just turning on sharding and launching multiple instances of your bot. It handles spreading events across them. The author throws away their own suggestion but it clearly works, works well, and scales well into "supermassive" size. They don't even mention the real downside to web sockets which is that they're stateful and necessarily tied to a particular server which makes them not mesh at all with your stateless share-nothing http servers.
- 0xbadcafebee 1y agoI just realized that modern web applications are a group form of procrastination. Procrastination is a complex thing. But essentially, it's putting something off because of some perceived pain, even though the thing may be important or even inevitable, and eventually the procrastination leads to negative outcomes. Web applications were created because people were averse to creating native applications, for fear of the pain involved with creating and distributing native applications. They were so averse to this perceived pain that they've done incredibly complex, even bizarre things, just so they don't have to leave the web browser. WebSockets are one of those things: taking a stateless client-server protocol (HTTP) and literally forcing it to turn into an entirely new protocol (WebSockets) just so people could continue to do things in a web browser that would have been easy in a native application (bidirectional stateful sockets, aka a tcp connection). I suppose this is a normal human thing. Like how we created cars to essentially have a horseless buggy. Then we created paved roads to make that work easier. Then we built cities around paved roads to keep using the cars. Then we built air-scrubbers into the cars and changed the fuel formula when we realized we were poisoning everyone. Then we built electric cars (again!) to try to keep using the cars without all the internal combustion issues. Then we built self-driving cars because it would be easier than expanding regional or national public transportation. We keep doing the easy thing, to avoid the thing we know we should be doing. And avoiding it just becomes a bigger pain in the ass.
- bonestamp2 1y agoI agree with a lot of that. But, it's a lot easier to get someone to try your web app than install a native app. It's also easier to get the IT department to allow an enterprise web app than install a native app. Web apps do have some advantages over native apps.
- 0xbadcafebee 1y agoYes, all of that is the reason why we procrastinate. "Easy" is the excuse we give ourselves to do the things we would otherwise have no justification for, and avoid the difficult things we know would be better. It's not my fault; it's not my responsibility; I shouldn't have to do extra work; it's too complicated; it'll be hard; it'll be long; it'll be painful; it's not perfect; it might fail. No worries; there's something easier I can do. Thus we see the flaws in the world, and shrug. When someone else does this, we get angry, and indignant. How dare someone leave things like this! Yet when we do it, we don't make a peep.
- SLWW 1y agoI don't need them but I do like them. I see the shiny thing and I'm not delusional enough to think I need it.
- defanor 1y agoI think an article like that would benefit from focusing more on protocols, rather than particular APIs to work with those: referencing the specifications and providing examples of messages. I am pretty sure that the article is about chunked transfer encoding [1], but it was not mentioned anywhere. Though possibly it tries to cover newer HTTP versions as well, abstracting from the exact mechanisms. In which case "JS API" in the title would clarify it. As for the tendency described, this seems to be an instance of the law of the instrument [2], combined with some instruments being more trendy than others. Which comes up all the time, but raising awareness of more tools should indeed be useful. [1] https://en.wikipedia.org/wiki/Chunked_transfer_encoding https://en.wikipedia.org/wiki/Chunked_transfer_encoding [2] https://en.wikipedia.org/wiki/Law_of_the_instrument https://en.wikipedia.org/wiki/Law_of_the_instrument
- andersmurphy 1y agoYou don't need websockets SSE works fine for realtime collaborative apps. Websockets sound great on paper. But, operationally they are a nightmare. I have had the misfortune of having to use them at scale (the author of Datastar had a similar experience). To list some of the challenges: - firewalls and proxies, blocked ports - unlimited connections non multiplexed (so bugs lead to ddos) - load balancing nightmare - no compression. - no automatic handling of disconnect/reconnect. - no cross site hijacking protection - Worse tooling (you can inspect SSE in the browser). - Nukes mobile battery because it hammers the duplex antenna. You can fix some of these problems with websockets, but these fixes mostly boil down to sending more data... to send more data... to get you back to your own implementation of HTTP. SSE on the other hand, by virtue of being regular HTTP, work out of the box with, headers, multiplexing, compression, disconnect/reconnect handling, h2/h3, etc. If SSE is not performant enough for you then you should probably be rolling your own protocol on UDP rather than using websockets. Or wait until WebTransport is supported in Safari (any day now ). Here's the article with a real time multiplayer Game of Life that's using SSE and compression for multiplayer. https://example.andersmurphy.com https://example.andersmurphy.com It's doing a lot of other dumb stuff explained a bit more here, but the point is you really really don't need websockets (and operationally you really don't want them): https://andersmurphy.com/2025/04/07/clojure-realtime-collaborative-web-apps-without-clojurescript.html https://andersmurphy.com/2025/04/07/clojure-realtime-collabo...
- EarthLaunch 1y agoUseful take, thanks for mentioning specifics. Some of these I wasn't aware of. - What makes load balancing easier with SSE? I imagine that balancing reconnects would work similar to WS. - Compression might be a disadvantage for binary data, which WS specializes in. - Browser inspection of SSE does sound amazing. - Mobile duplex antenna is way outside my wheelhouse, sounds interesting. Can you see any situation in which websockets would be advantageous? I know that SSE has some gotchas itself, such as limited connections (6) per browser. I also wonder about the nature of memory and CPU usage for serving many clients on WS vs SSE. I have a browser game (few players) using vanilla WS.
- 1y ago
- Voultapher 1y agoHaving deployed WebSockets into production, I came to regret that over the next years. Be it ngnix terminating connections after 4/8 hours, browsers not reconnecting after sleep and other issues, I am of the opinion that WebSockets and other forms of long standing connections should be avoided if possible.
- bonestamp2 1y agoNot to mention, some major parts of the websocket API have been broken in Google Chrome for over two years now. Chrome no longer fires Close or Error events when a websocket disconnects (well, at least not when they happen, they get fired about 10 minutes later!). So, your application won't know for 10 minutes that the connection has been severed (unless the internet connection is also lost, but that isn't always the case when a websocket is disconnected). Here's the chrome bug: https://issuetracker.google.com/issues/362210027?pli=1 https://issuetracker.google.com/issues/362210027?pli=1 From that bug report it looks like the Chrome bug is less than a year old, but the Chrome bug is originally mentioned here in April 2023 for a similar bug in iOS (the iOS bug has been resolved): https://stackoverflow.com/questions/75869629/ios-websocket-close-and-error-events-not-firing https://stackoverflow.com/questions/75869629/ios-websocket-c... I kind of suspect Chrome is actually doing this intentionally. I believe they do this so a tab can recover from background sleep without firing a websocket close event. That's helpful in some cases, but it's a disaster in other cases, and it doesn't matter either way... it breaks the specification for how websockets are expected to work. WebSockets should always fire Close and Error events immediately when they occur.
- Sammi 1y agoIf you want to use websockets, then you are most definitely going to need some library that wraps the websocket, because websockets themselves are very simple and don't do things like reconnect on their own. This one is pretty simple and pretty great: https://github.com/lukeed/sockette https://github.com/lukeed/sockette I did my own which provides rpc functionality and type safety: https://github.com/samal-rasmussen/smolrpc https://github.com/samal-rasmussen/smolrpc
- dontlaugh 1y agoEven load balancers force you to have a frequent heartbeat all the way to the client for each connection.
- il-b 1y agoI usually start with the long polling/SSE and migrate to WebSockets when needed. It is cheap and reliable with almost no performance overhead when compared to WebSockets.
- gabesullice 1y agoThis feels ill advised and I don't believe that HTTP streaming was designed with this pattern in mind Perhaps I'm wrong, but I believe HTTP streaming is for chunking large blobs. I worry that if you use this pattern and treat streaming like a pub/sub mechanism, you'll regret it. HTTP intermediaries don't expect this traffic pattern (e.g., NGINX, CloudFlare, etc.). And I suspect every time your WiFi connection drops while the stream is open, the fetch API will raise an error as if the request failed. However, I agree you probably don't need WebSockets for many of the ways they're used—server-sent events are a simpler solution for many situations where people reach for WebSockets... It's a shame SSEs never received the same fanfare.
- hobofan 1y agoWith the current AI/LLM wave SSE have received a lot of attention again, and most LLM chat frontends use them. At least from my perception as a result of this, support for SSEs in major HTTP server frameworks has improved a lot in the last few years. It is a bit of a shame though, that in order to do most useful things with SSEs you have to resort to doing non-spec-compliant things (e.g. send initial payload with POST).
- blensor 1y agoAlso MCP uses it
- ljm 1y agoSame with graphql subscriptions. Arguably it’s also because of serverless architecture where SSE can be used more easily than WS or streaming. If you want any of that on Lambda and API Gateway, for example, and didn’t anticipate it right off the bat, you’re in for quite a bit of pain.
- nkozyra 1y agoSSE limitations in the browser are still a drag for this, too.
- skrebbel 1y ago> I don't believe that HTTP streaming was designed with this pattern in mind > server-sent events are a simpler solution Fwiw Server-Sent Events are a protocol on top of HTTP Streaming. In fact I'm somewhat surprised that the article doesn't mention it, instead rolling their own SSE alternative that looks (to my non-expert eyes) like a lower level version of the same thing. It seems a bit weird to me to use chunks as a package boundary, I'd worry that that has weird edge cases (eg won't large responses be split into multiple chunks?)
- z3t4 1y agoWeb sockets are very low level, so first you want to use a library in order to work seamlessly with all 100 different implementations of websockets, but then you need to make your own protocol ontop of it. And implement ping and reconnect.
- austin-cheney 1y agoWebSockets are full duplex, so both sides of a connection are equally transmitting sides. There first section fails to understands this and then builds some insane concern for state on top of this faulty notion. WebSockets don't care about your UI framework just like your car doesn't care what time you want to eat dinner. > You have to manage the socket lifecycle You have to do the very same thing with HTTP keep-alive or use a separate socket for each and every HTTP request, which is much slower. Fortunately the browser makes this stupid simple in regards to WebSockets with only a few well named events. > When a new WebSocket connection is initiated, your server has to handle the HTTP “upgrade” request handshake. If the author cannot split a tiny string on CRLF sequences they likely shouldn't be programming and absolutely shouldn't be writing an article about transmission. There is only 1 line of data you really need from that handshake request: Sec-WebSocket-Key. Despite the upgrade header in the handshake the handshake is not actually HTTP. According to RFC6455 it is a tiny bit of text conforming to the syntax of RFC2616, which is basically just: lines separated by CRLF, terminated by two CRLFs, and headers separated from values with a colon. Really its just RFC822 according to RFC2616. This is not challenging. I take it this article is written by a JavaScript framework junkie that cannot program, because there is so much in the article that is just wrong. EDITED: because people get sad.
- skrebbel 1y agoYou're very confrontational yet your post doesn't really refuse the author's main points. What the author means with "transactional" is that WebSockets have no built-in request-response mechanism, where you can tell which response belongs to which request. It's a weird word choice, but alas. I do agree that the bit about "handshakes are hard" feels a bit ill-advised btw, but it's not the core argument nor the core idea of this post. The core idea is "do request-response via HTTP, and then use some sort of single-direction stream (maybe over WS, doesn't matter) to keep client state in sync". This is a pretty good idea regardless of how well or how badly you know the WebSocket RFCs by heart. (I say this as someone who built a request-response protocol on top of websockets and finds it to work pretty well)
- austin-cheney 1y ago
- jFriedensreich 1y agoI don't know why the topic of websockets is so weird. 80% of the industry seem to have this skewed idealised perception of websockets as the next frontier of their web development career and cannot wait to use them for anything remotely connected to streaming/ realtime use cases. When pointing out the nuances and that websockets should actually be avoided for anything where they are not absolutely needed without alternatives people get defensive and offended, killing every healthy discussion about realistic tradeoffs for a solution. Websockets have a huge number of downsides especially losing many of the niceties and simplicity of http tooling, reasonability, knowledge and operations of http. As many here pointed, the goto solution for streaming server changes is h2 / h3 and SSE. Everything that can be accomplished in the other direction with batching and landing in the ballpark of max 0.5req/s per client does NOT need websockets.
- austin-cheney 1y agoThere is no reason to avoid WebSockets. This is a conclusion people come to because they are familiar with HTTP round trips and cannot imagine anything different. There are no nuances to understand. It’s as simple as fire and forget. The only downside to WebSockets is that they are session oriented. Conversely, compared to WebSockets the only upside to HTTP is that its sessionless.
- ofrzeta 1y agoWhy not use a library like socket.io? It handles the socket lifecycle, reconnection etc.
- revskill 1y agoSetinterval.
- manmal 1y agoWe are looking into adopting bidirectional streams, and have identified gRPC as a likely ideal candidate. It provides a layer on top of the blobs (partial responses) sent by either side, and takes over the required chunking and dechunking. And it doesn’t have the authentication issues that Websockets have. I‘d appreciate any insights on this matter.
- raluk 1y agoWebsocket is not ment to be sent as streams (TCP equvalent), but as datagrams aka packets (UDP equivalents). Correct me if I am wrong, but websockets api in Javascript libraray for browsers is pretty poor and does not have ability to handle backpressure and I am sure it can not handle all possible errors (assertions about delivery). If you want to use websockets as TCP streams including seasson handling, great care should be taken as this is not natively availabe in neither rfc6455 and in browser.
- retropragma 1y agoIf you use a proper framework, you don't have to manage the socket lifecycle and it doesn't complicate your server.