[HN Gopher] WebSockets vs. Server-Sent-Events vs. Long-Polling v...
       ___________________________________________________________________
        
       WebSockets vs. Server-Sent-Events vs. Long-Polling vs. WebRTC vs.
       WebTransport
        
       Author : bubblehack3r
       Score  : 152 points
       Date   : 2024-03-18 15:36 UTC (7 hours ago)
        
 (HTM) web link (rxdb.info)
 (TXT) w3m dump (rxdb.info)
        
       | kevmo314 wrote:
       | 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.
        
         | mmis1000 wrote:
         | SSE isn't really more complex than long polling. The only
         | difference is the server don't close the connection immediately
         | after sent the response. Instead, it wait for data again and
         | send more response using the same stream.
        
           | jacobr1 wrote:
           | Agreed - I see SSE as basically a standardized approach to
           | modern long polling
        
           | jallmann wrote:
           | Long polling is more amenable than SSE for most HTTP tools
           | out of the box, eg curl. The SSE message body is notably
           | different from plain HTTP responses.
           | 
           | To the OP, you can still build APIs with long polling. They
           | are uncommon because push patterns are difficult to design
           | well, regardless of protocol (whether long-polling, SSE,
           | websockets, etc).
           | 
           | Whiteboarding a push API is a good exercise. There is a lot
           | of nuance that gets overlooked in discussions whenever these
           | patterns come up.
        
             | kevmo314 wrote:
             | Well I know _I_ can write applications use it, but I don 't
             | often write code outside the context of a team that has
             | other opinions anymore :)
        
           | apitman wrote:
           | One limitation of SSE compared to long polling (and
           | WebSockets etc) is you can't efficiently send binary data
           | such as cbor, protobuf, etc. Though if your long polling is
           | chatty enough eventually the HTTP overhead will kill your
           | efficiency too.
        
         | ramesh31 wrote:
         | >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.
         | 
         | I still use it all the time. There are plenty of applications
         | where the request overhead is reasonable in exchange for
         | keeping everything within the context of an existing HTTP API.
        
         | Animats wrote:
         | Oh, if only it were that simple.
         | 
         | The networking that makes Second Life go uses long polling
         | HTTPS for an "event channel", over which the server can send
         | event messages to the clients. Most messages go over UDP, but a
         | few that need encryption or are large go over the HTTPS/TCP
         | event channel.
         | 
         | At the client end, C++ clients use "libcurl". Its default
         | timeout settings are not compatible with long polling. Libcurl
         | will break connections and make another request. This can
         | result in lost or duplicated messages.
         | 
         | At the server end, Apache front-ends the actual simulation
         | servers, to filter out irrelevant connection attempts (Random
         | HTTP attacks that try any open port, probably). Apache has its
         | own timeouts, and will abort connections, forcing the client to
         | retry.
         | 
         | There's a message serial number to try to prevent this
         | mechanism from losing messages. The Second Life servers ignore
         | the serial number the client sends back as a check. Some
         | supposedly compatible servers from Open Simulator skip
         | sequential numbers.
         | 
         | The end result is an HTTPS based system which can both lose and
         | duplicate what were supposed to be reliable messages. Some of
         | those messages, if lost, will stall out the user's activity in
         | the game. The people who designed this are long gone. The
         | current staff was unaware of how bad the mess is. Outside users
         | had to find the problem and document it. The company staff has
         | been trying to fix this for months. It seems to be difficult
         | enough to fix that the current action is to defer work on the
         | problem.
         | 
         | So, no, long polling is not "stupidly simple".
         | 
         | The right way to do this is probably to send a keep-alive
         | message frequently enough that the TCP and HTTPS levels never
         | time out. This keeps Apache and libcurl on their "happy paths",
         | which work.
        
           | jallmann wrote:
           | My solution to broken connections has actually been to have
           | relatively short timeouts by default, eg 10 seconds. That
           | guarantees we have a fresh connection every so often without
           | any assumptions about liveness. You can even overlap the
           | reconnects a bit (eg 10 second request timeouts, but
           | reconnect every 8 seconds) as long as the application can
           | reconcile duplicated messages - which it should be able to do
           | anyway, for robustness reasons.
           | 
           | Really, anytime there is any form of push (whether SSE, long
           | polling, etc) then you need another way to re-hydrate to the
           | full state. In which case you are nearly at the point of
           | doing plain old polling to sidestep the complexity of server-
           | driven incremental updates and all the state coordination
           | problems that entails.
           | 
           | Of course with polling, you lose responsiveness. For latency-
           | sensitive applications (like an interactive mmorpg!) then
           | HTTP is probably not the correct protocol to use.
           | 
           | It does sound like Second Life has its own special blend of
           | weirdness on top of all that. Condolences to the engineers
           | maintaining their systems.
        
             | mjevans wrote:
             | I've seen a bunch of timeouts / heartbeat / keep alive
             | durations. I think it might have been Wireguard, but _25
             | seconds_ seems like a good number. Usefully long, most
             | things that break are more likely to do it at ~30 seconds,
             | and if there 's an active activity push at 15 or 20 seconds
             | with device wakeup then the keep alive / connection kill
             | might not even happen.
             | 
             | Full Refresh; yes please, in the protocol, with a user
             | button, with local client state cached client code and
             | reloaded state on reconnect. Maybe even a configurable
             | polling period; some services might offer shorter poll as a
             | reason to pay for a higher tier account.
        
       | kellengreen wrote:
       | I've always had a bit of a soft spot for Server Sent Events. Just
       | simple and easy to use/implement.
        
         | djbusby wrote:
         | Works with bog-standard Apache prefork and PHP.
        
         | marban wrote:
         | Absolutely underrated.
        
         | ajvpot wrote:
         | I agree. Unfortunately you can only have 6 SSE streams per
         | origin per browser instance, so you may be limited to 6 tabs
         | without adding extra complexity on the client side.
         | 
         | https://crbug.com/275955
        
           | TheP1000 wrote:
           | Is above still an issue with http2/3?
           | 
           | edit: From the article: To workaround the limitation you have
           | to use HTTP/2 or HTTP/3 with which the browser will only open
           | a single connection per domain and then use multiplexing to
           | run all data through a single connection.
        
           | ravxx wrote:
           | just use a service worker to share state, you would be much
           | better off doing this anyways. saves a ton and is performant.
        
             | simonw wrote:
             | I think you need a SharedWorker for that rather than a
             | service worker https://developer.mozilla.org/en-
             | US/docs/Web/API/SharedWorke...
        
           | simonw wrote:
           | Is that true if you are using HTTP/2?
        
           | andrewmutz wrote:
           | You can get around that limit using domain sharding, although
           | it feels a bit hacky.
        
           | nine_k wrote:
           | Can the tabs share a background worker that would handle
           | that?
        
             | merb wrote:
             | You can use https://www.npmjs.com/package/broadcast-channel
             | which creates a tab leader, no need for a background worker
             | 
             | Edit: of course you could use:
             | https://caniuse.com/sharedworkers but android does not
             | support it. We migrated to the lib because safari took its
             | time... so mobile was/is not a thing for us
        
         | shams93 wrote:
         | With ipv6 they can now be fully scaled easily but they are
         | absolutely awesome, much easier to scale because you can give
         | your client a simple list of sse services and its essentially
         | stateless if done right.
         | 
         | Websockets get really complex to scale past a certain level of
         | use.
        
           | apitman wrote:
           | > With ipv6 they can now be fully scaled easily
           | 
           | Any day now:
           | https://www.google.com/intl/en/ipv6/statistics.html
        
         | spintin wrote:
         | SSE are really a subset of Comet-Stream (eternal HTTP response
         | with Transfer-Encoding: chunked) only they use a header
         | (Accept: text/event-stream) and wraps the chunks with "data:"
         | and "\n\n".
         | 
         | But yes it's the superior (simplest, most robust, most
         | performant and scalable) way to do real-time for eternity.
         | 
         | The browser is dead, but SSE will keep on doing work for native
         | apps.
        
       | bterlson wrote:
       | 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.
        
         | mmis1000 wrote:
         | Server send event IS http response streaming. It is a
         | standardized way to implement response streaming.
        
           | bterlson wrote:
           | I agree, but SSE is a more complex protocol that requires
           | additional handling on both client and server, with
           | capabilities that may not be relevant for your use case
           | (multiple event types, event id). For JS clients and JS
           | servers it is not particularly onerous to implement, but for
           | other ecosystems can require a fair bit of code. JSONL
           | streaming is very easy to implement on both ends, so all else
           | aside I think would be preferred if all you really want to do
           | is stream JSON values.
        
             | apitman wrote:
             | I've implemented SSE from scratch on the server and XHR
             | streaming/parsing from scratch on the client side (which
             | would be necessary for JSONL), and SSE was way simpler.
             | Unless there's another way to do JSONL in a browser that
             | I'm not aware of?
        
               | bterlson wrote:
               | If you use the fetch API you can get a readable stream
               | and party on without too much difficulty. You can also
               | implement a transform stream in ~10SLOC that will make
               | the reader vend parsed JSON objects and can be reused
               | easily.
        
       | rvanmil wrote:
       | 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.
        
         | chgs wrote:
         | My browser has a refresh button. Alas your application likely
         | breaks when I use it.
        
           | rvanmil wrote:
           | Not entirely sure why it would break...?
        
             | klysm wrote:
             | client side state that isn't in the URL or local storage
        
             | chgs wrote:
             | Clearly I don't know what _your_ application is, but many
             | heavyweight "web apps" don't cope with a simple refresh,
             | kicking back to a default screen or even login screen in
             | some cases.
        
         | cbsmith wrote:
         | Honestly, all the techniques for this stuff have their
         | problems, including the refresh button.
        
           | rvanmil wrote:
           | True, though when carefully implemented it's the most
           | reliable option I guess.
        
             | cbsmith wrote:
             | I've switched to using SSE to get around problems with the
             | refresh button. It's pretty simple and reliable.
        
               | rvanmil wrote:
               | That's great. Unfortunately I've seen SSE fail quite a
               | few times in the scenario I described.
        
       | ravxx wrote:
       | Whoever made this article is pretty clueless. The article states
       | using WebRTC would be pointless since you need to run it over
       | websockets, sse, or webtransport, but forgets to mention the main
       | benefit of WebRTC is that it can be done with UDP. Which is why I
       | expect it was faster in the results... I am shocked to not even
       | see UDP mentioned in this article.
        
         | realPubkey wrote:
         | Author here. The article is mostly about web apps. How would
         | your signaling server emit new connection updates to clients in
         | the scenario you describe?
        
           | andreigheorghe wrote:
           | I think what they mean is that yes, the signalling needs to
           | be done over "traditional" web APIs (websockets, etc), but
           | that's just for discovering/negotiating the p2p connections.
           | The actual data transfer between the peers then happens over
           | UDP which can have a bunch of advantages over TCP for some
           | scenarios.
        
         | cbsmith wrote:
         | The WebRTC section of the article seemed weird in general. The
         | reason WebRTC doesn't specify signaling requirements is that
         | clients can use any communications mechanism they'd like for
         | signaling, and in the case where you are using WebRTC as sever-
         | push mechanism, the "signaling" server and the server you want
         | to receive pushes from could be the same server, allowing the
         | use of "regular" HTTP as the transport for your "signaling"
         | data.
         | 
         | With QUIC & HTTP/3, and things like RFC 8441 & 9220, you could
         | well be using UDP with non-WebRTC protocols, and TCP stacks &
         | routers tend to be pretty well tuned these days, so UDP doesn't
         | _necessarily_ have much of an advantage in this kind of use
         | case.
         | 
         | If you check out the benchmark the article uses, it
         | specifically breaks out using "unreliable WebRTC/WebTransport".
         | The "unreliable" looks to be referring to UDP (I despise how
         | people misleadingly associate UDP with "unreliable"). They also
         | have "reliable WebRTC/WebTransport", which appears to be using
         | TCP. In the latter case, they actually found in some cases
         | WebTransport doing a tad better in the face of packet loss,
         | which is interesting. I haven't looked at the details of the
         | tests, but in my experience benchmarching WebRTC is not as
         | straightforward as one might expect; it's entirely possible the
         | nature of the benchmark itself is leading to WebRTC's better &
         | worse performance.
        
         | paulgb wrote:
         | > Whoever made this article is pretty clueless
         | 
         | This genre of HN comment irks me. Technical writing is an
         | exercise in taking a lot of material and distilling it down to
         | an audience. Writing that does a good job this will often look
         | basic to someone with a deep understanding of the tech. It
         | doesn't mean the author is clueless, it just means they decided
         | they made different decisions on what to cut than you would
         | have.
        
           | kordlessagain wrote:
           | That the author didn't mention UDP "leaves out" the vs.
           | objective, however. If it were a fair contest, the article
           | would mention the use of WebRTC over UDP, which isn't just
           | for streaming media (an assumption I had before doing a bit
           | more research on it).
           | 
           | > This article aims to delve into these technologies,
           | comparing their performance, highlighting their benefits and
           | limitations, and offering recommendations for various use
           | cases to help developers make informed decisions when
           | building real-time web applications.
           | 
           | So, the article's _intent_ was to help others. When we do
           | things like this, we should ensure all technologies being
           | evaluated will be covered exhaustively. Otherwise, you risk
           | leaving out an important part of the puzzle and then
           | assumptions kick in which ignore a possible better solution
           | for a given use case.
           | 
           | It looks like UDP use is possible between a browser and a
           | server, and that connection has to have components that deal
           | with dropout, given it's UDP. There is a LOT to consider and
           | deal with implementing UDP over WebRTC, so I put a dump of
           | this up here: https://pastebin.com/xgA78dky
        
       | mirekrusin wrote:
       | 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).
       | 
       | [0] https://github.com/simdjson/simdjson
        
         | cbsmith wrote:
         | It's been a while since I've used websockets, but at least the
         | last time I did, "simple" wouldn't be the word I'd have used.
         | All kinds of annoying issues between different browsers. SSE
         | was generally much simpler.
        
           | mirekrusin wrote:
           | Must have been time when spec wasn't stabilized and browsers
           | have been introducing it. Those times are long gone.
        
             | cbsmith wrote:
             | I don't know about long gone. I still support a websocket
             | solution that needs to have server-push as a fallback
             | because of browser incompatibility issues.
        
               | apitman wrote:
               | Do you have some specific examples?
        
               | cbsmith wrote:
               | Old Android handsets seem to be the big ones.
        
               | mirekrusin wrote:
               | It shouldn't be a problem for about a decade [0]?
               | 
               | What's your hit rate for the fallback?
               | 
               | [0] https://developer.mozilla.org/en-
               | US/docs/Web/API/WebSocket
        
               | cbsmith wrote:
               | The hit rate for fallback is pretty low. It was less than
               | 5% the last I checked.
        
       | cbsmith wrote:
       | 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.
        
         | switchbak wrote:
         | I've spent so many hours trying to communicate to folks the
         | importance of HTTP streaming ... it's an uphill challenge for
         | sure.
         | 
         | Yes, all the benefits of http/2 (or 3) are great, but we should
         | also be aware of what we can take advantage of in http 1.1,
         | especially since it's effectively universally supported.
        
           | cbsmith wrote:
           | Hello fellow traveler. ;-)
           | 
           | Nobody reads the specs anymore, and to a certain degree I
           | can't blame them, as the protocols/standards have become
           | quite complicated.
        
           | merb wrote:
           | Actually what he meant is not supported anymore: https://en.m
           | .wikipedia.org/wiki/Push_technology#HTTP_server_...
           | 
           | Comet/sse/chunked transfer needs xhr to work. x-mixed-replace
           | was wurd back in the days and still is.
           | 
           | Edit: maybe you could also use an iframe/frame which holds a
           | chunked connection but that will only give you text.
        
             | cbsmith wrote:
             | Chunked transfer encoding (which is indeed the underlying
             | mechanism behind server-push) predates XHR, and AFAIK is
             | still supported and will continue to be as long as HTTP/1.1
             | is still supported.
             | 
             | You can use a frame/iframes, but you can also just have
             | content that is updated with multi-part MIME that doesn't
             | cause the page layout to be redone.
        
               | merb wrote:
               | x-mixed-replace Was the only mechanism that did that and
               | chrome removed it and it is not standard and never was
        
               | contravariant wrote:
               | I'm so confused. Was x-mixed-replace the only way to use
               | chunked transfer encoding (which _is_ part of the HTTP
               | standard) or are you talking about something else
               | entirely?
        
               | merb wrote:
               | actually you can use transfer encoding chunked to stream
               | data , but it will get appended and the page would never
               | finish loading, that worked back than it works today but
               | that is not useful for several reasons and wasn't back
               | than.
               | 
               | with x-mixed-replace (as the name implies x-:
               | experimentell) you can stream the page over and over
               | again and the browser would change to the new version.
               | (chrome still supports that for images, cheap webcams)
               | 
               | Tbf without frames neither mechanism made much sense,
               | (even back than) because it would be horrible to use with
               | form fields.
               | 
               | I started to play with the web in the early 2000s where
               | xhr/long-polling/comet(via iframes, later it used xhr
               | onreadystatechange with chuncked encoding, without sse,
               | which basically was created because of that) started to
               | gain traction and x-mixed-replace was extremely niche
               | even back than because of the limitations it had on the
               | page
               | 
               | Edit: comet (streaming script tags, inside an iframe) of
               | course worked, back then. But I never heard of an
               | implementation before 2006 (maybe a few years earlier
               | like 2-3)or so, would've been worth a Wikipedia change if
               | you would have old entries. Also http/1.1 was 97
        
               | cbsmith wrote:
               | > actually you can use transfer encoding chunked to
               | stream data , but it will get appended and the page would
               | never finish loading, that worked back than it works
               | today but that is not useful for several reasons and
               | wasn't back than.
               | 
               | Oh Server Push has all kinds of issues with it. There are
               | lots of good reasons to prefer the newer protocols for a
               | lot of use cases.
        
       | arendtio wrote:
       | I wonder why mobile push notifications are just a side-note in
       | this article as mobile clients are responsible for a large part
       | of the global traffic.
        
         | nine_k wrote:
         | Aren't mobile push notifications an _entirely_ different tech,
         | one that significantly uses the capabilities of mobile
         | carriers?
        
           | slt2021 wrote:
           | iOS and android push does not rely on mobile carrier
           | capability afaik, it has its own service
        
             | psnehanshu wrote:
             | Yes, iOS has APNS and Android has FCM. One can use FCM for
             | both Android and iOS as FCM is capable of abstracting away
             | APNS. If you are building on React Native with Expo, you
             | can also use Expo Push, which abstracts away both APNS and
             | FCM, albeit it is not fully featured.
        
           | cbsmith wrote:
           | You can do mobile push notifications to a phone even if they
           | aren't connected to a mobile carrier.
           | 
           | That said, I'd argue SSE is the browser equivalent of mobile
           | push notifications.
        
             | jallmann wrote:
             | SSE generally requires the page to be active in the
             | foreground, which is not a viable solution for mobile.
             | 
             | Web Push is a distinct API for browsers to emulate native
             | push notifications via service workers.
             | https://developer.mozilla.org/en-US/docs/Web/API/Push_API
        
               | cbsmith wrote:
               | I thought it was more that the Document object had to
               | stay alive. ...although, these days a lot of mobile
               | browsers will kill that thing off if the page is not in
               | the background, so yeah...
        
           | arendtio wrote:
           | I don't know about the implementation details, but even the
           | use case is slightly different, as the discussed techs are
           | also meant to transfer larger amounts of data. At the same
           | time, mobile push is more about triggering synchronization
           | than transferring large amounts of data.
           | 
           | However, since the discussed techs all have major problems
           | with mobile connections, I still think it should have been
           | discussed in more depth.
        
       | skybrian wrote:
       | 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.
       | 
       | (This all assumes you only care about maintaining a connection
       | when the tab is in the foreground.)
       | 
       | I'm wondering what problems people have run into when they tried
       | this.
        
         | jacobr1 wrote:
         | This presumes the majority of your use case is server-client,
         | but otherwise yes.
        
         | apitman wrote:
         | One limitation is SSE is text-only, so you can't efficiently
         | send binary data. You have to encode it as base64 or similar.
        
       | Fabricio20 wrote:
       | 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.
       | 
       | 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.
        
         | omgtehlion wrote:
         | Wait, what?? Been using these for years. Am I missing
         | something?
        
           | apitman wrote:
           | They're probably referring to browsers specifically. The
           | WebSocket constructor doesn't allow for headers
        
           | tytho wrote:
           | The browser EventSource constructor does not have options to
           | pass in your own headers. You can pass an option to have it
           | use the cookies for the domain you're using. There are
           | libraries that allow you to pass in additional HTTP options,
           | but they essentially reimplement the built-in EventSource
           | object in order to do so. Not terribly difficult, fairly
           | simple spec.
        
             | omgtehlion wrote:
             | Well, that constructor by default sends all the headers you
             | have for your own domain and auth you are entitled to. This
             | is how all other APIs in browsers work due to security and
             | privacy concerns.
             | 
             | If you call to other domains, then this problem is no
             | different to what we had with CORS years ago.
        
               | apitman wrote:
               | > This is how all other APIs in browsers work due to
               | security and privacy concerns
               | 
               | They're probably comparing it to the fetch and XHR APIs,
               | which both allow custom headers.
        
         | michaelt wrote:
         | _> To this day I still dont know why WebSockets and SSE dont
         | support sending headers on the initial request_
         | 
         | Doesn't the initial request get to send a full set of standard
         | HTTP headers, cookies and all?
        
           | paulgb wrote:
           | It does, but if you're calling it from the browser you can't
           | add arbitrary data to them (the way you can in e.g. a
           | `fetch`)
        
             | makkesk8 wrote:
             | Someone at Azure thought of this[1]
             | 
             | [1] https://github.com/Azure/fetch-event-source
        
             | pier25 wrote:
             | > _you can 't add arbitrary data to them_
             | 
             | What about intercepting the request with a service worker?
        
         | dist-epoch wrote:
         | They do send cookies.
        
         | cbsmith wrote:
         | There's always TLS certificates... ;-)
        
         | paol wrote:
         | Oooh boy you touched a pet peeve. I mean who needs
         | authentication on the modern Web right? /s
         | 
         | The even more irritating thing is that there is nothing
         | preventing this, and every server I've tried supports it. It's
         | only the _browser_ WebSocket API that was designed without
         | this. Cookies are the only thing browsers will deign to send in
         | the initial request.
        
       | EGreg wrote:
       | 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?
        
         | psnehanshu wrote:
         | Don't assume reliability
        
       | apitman wrote:
       | A few additional cons to be aware of:
       | 
       | WebSockets lack flow control (backpressure) and multiplexing, so
       | if you need them you either roll your own or use something
       | similar to RSocket.
       | 
       | Also SSE can't send binary data directly. You have to base64
       | encode it or similar.
       | 
       | 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.
       | 
       | As long as browsers still work with TCP, some networks will
       | continue to block UDP (and thus HTTP3/WebTransport) outright.
        
         | cbsmith wrote:
         | > WebSockets lack flow control (backpressure) and multiplexing,
         | so if you need them you either roll your own or use something
         | similar to RSocket.
         | 
         | Yes, head of line blocking is an issue, but TCP provides flow
         | control, and if you're not using that, you're going over HTTP3.
         | 
         | > 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.
         | 
         | At one time or another, one could have said the same thing
         | about TLS transport, HTTP3, or XHR itself. Because of the
         | comparatively huge domination of a few key browser engines,
         | it's much easier to roll out new browser capabilities &
         | protocols.
         | 
         | > As long as browsers still work with TCP, some networks will
         | continue to block UDP (and thus HTTP3/WebTransport) outright.
         | 
         | By that logic, as long as browsers still work with HTTP 1.1
         | without TLS, some networks will continue to block HTTP 2 and
         | TLS. While that's not entirely incorrect, the broad adoption of
         | HTTP2 and TLS in particular suggests it's less of a problem
         | than you think.
        
           | apitman wrote:
           | > Yes, head of line blocking is an issue, but TCP provides
           | flow control
           | 
           | Unfortunately, the way browsers implement WebSocket it
           | undermines TCP's flow control. It's trivial to crash a
           | browser tab by opening a (larger than RAM) file and trying to
           | stream it to a server using a tight loop sending on a
           | WebSocket. WebSocket.bufferedAmount exists, but as of 2019 I
           | failed to use it to solve this problem and had to implement
           | application-level backpressure.
           | 
           | > At one time or another, one could have said the same thing
           | about TLS transport, HTTP3, or XHR itself. Because of the
           | comparatively huge domination of a few key browser engines,
           | it's much easier to roll out new browser capabilities &
           | protocols.
           | 
           | > By that logic, as long as browsers still work with HTTP 1.1
           | without TLS, some networks will continue to block HTTP 2 and
           | TLS. While that's not entirely incorrect, the broad adoption
           | of HTTP2 and TLS in particular suggests it's less of a
           | problem than you think.
           | 
           | HTTP3 actually falls under my concern. There are still
           | networks that block HTTP3, because it has really nice
           | fallback to HTTP2/1.1, so there's no obvious impact on users.
           | 
           | So I guess the real question is will QUIC be an HTTP/2 or an
           | IPv6, or something in between? Was HTTP/2 ever actively
           | blocked the way UDP is? If so that certainly gives us hope.
           | 
           | The reason I care is that I'm currently developing a protocol
           | that WebTransport is an excellent fit for. But I can't assume
           | WebTransport will work because UDP might be blocked, so I'm
           | having to implement WebSocket support as well, which is a lot
           | more work.
        
             | 0x457 wrote:
             | HTTP/2 traffic was looking essentially the same as HTTP/1.1
             | + TLS.
             | 
             | It wasn't particularly interesting to block to begin with.
             | UDP if blocked, then it's blocked in a name of Security.
        
             | cbsmith wrote:
             | > Unfortunately, the way browsers implement WebSocket it
             | undermines TCP's flow control. It's trivial to crash a
             | browser tab by opening a (larger than RAM) file and trying
             | to stream it to a server using a tight loop sending on a
             | WebSocket. WebSocket.bufferedAmount exists, but as of 2019
             | I failed to use it to solve this problem and had to
             | implement application-level backpressure.
             | 
             | Before you were saying, "WebSockets lack flow control
             | (backpressure) and multiplexing, so if you need them you
             | either roll your own or use something similar to RSocket.",
             | and now you're saying you can't roll your own? ;-)
             | 
             | > HTTP3 actually falls under my concern. There are still
             | networks that block HTTP3, because it has really nice
             | fallback to HTTP2/1.1, so there's no obvious impact on
             | users.
             | 
             | Erm, HTTP2 & HTTP 1.1 have their own problems, some of
             | which you yourself have identified. We actually rolled back
             | from HTTP2 to HTTP 1.1 because of problems with HTTP2,
             | particularly with mobile performance.
             | 
             | Our migration to HTTP3 has been all win so far. While UDP
             | might be blocked for security reasons, there are security
             | reasons to move to HTTP3.
             | 
             | That said, there are cases where only HTTP/1.0 is
             | supported.
             | 
             | > The reason I care is that I'm currently developing a
             | protocol that WebTransport is an excellent fit for. But I
             | can't assume WebTransport will work because UDP might be
             | blocked, so I'm having to implement WebSocket support as
             | well, which is a lot more work.
             | 
             | I feel your pain. I've been using WebRTC, and the vast
             | majority of the time UDP doesn't seem to be blocked
             | anymore. That said, adoption of HTTP3 seems to be about
             | half that of HTTP2 right now. Not bad for a brand new
             | protocol, but I'd say we still have a significant amount of
             | time to go before HTTP3 is the dominant protocol. I think
             | the path forward is going to require some toil by the likes
             | of you to support both, but no reason you can't support
             | HTTP3 better! ;-)
        
         | 0x457 wrote:
         | > As long as browsers still work with TCP, some networks will
         | continue to block UDP (and thus HTTP3/WebTransport) outright.
         | 
         | I keep hearing it, but I've never actually seen such a network.
         | There are many things that run on UDP. I can see it being
         | closed in some tiny offices (but those usually lack brain power
         | to accomplish it) or some dystopian corporate offices you can
         | only see in a movie.
         | 
         | I really don't see how the fact that some networks might ban
         | UDP has anything to do with it. Some networks ban google.com
         | and wikipedia.com, you don't see them failing.
        
           | apitman wrote:
           | In their excellent article on NAT traversal[0], Tailscale
           | mentions that the UC Berkeley guest wifi blocks all outbound
           | UDP except DNS.
           | 
           | EDIT: According to this[1] issue, Berkeley guest wifi allows
           | port 443, which would solve HTTP3/WebTransport. That's
           | certainly hopeful, and I hope all networks are like this in
           | the future. It's just not a forgone conclusion yet.
           | 
           | [0]: https://tailscale.com/blog/how-nat-traversal-works#have-
           | you-...
           | 
           | [1]: https://github.com/danderson/natlab/issues/1
        
           | CodesInChaos wrote:
           | Not a traditional network, but Tor doesn't support UDP.
        
         | laurencerowe wrote:
         | > As long as browsers still work with TCP, some networks will
         | continue to block UDP (and thus HTTP3/WebTransport) outright.
         | 
         | HTTP2 should still work in that scenario then you don't need to
         | worry about multiplexing.
        
       | btown wrote:
       | 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.
       | 
       | I've come across https://github.com/soketi/soketi and
       | https://centrifugal.dev/ but not sure if there are more battle-
       | tested solutions.
        
         | roopakv wrote:
         | Another one to check out https://partykit.io
         | 
         | They are building on top of Cloudflare, and getting started is
         | a breeze.
         | 
         | That being said they are also fairly new, but based on
         | everything I have seen, I am a fan
        
         | jkarneges wrote:
         | There's also Pushpin, if you want the API to blend with your
         | existing app.
         | 
         | Disclosure: Pushpin lead dev.
        
       | eightnoteight wrote:
       | 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
       | 
       | 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.
       | 
       | 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
       | 
       | 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
        
         | debarshri wrote:
         | I cannot agree more with you. I have seen people shot
         | themselves on foot with Websockets and SSE. Long Polling even
         | though is expensive, is it most explainable and scalable
         | approach in my opinion.
        
       | ascii78 wrote:
       | 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.
        
         | Sean-Der wrote:
         | Works well! Lots of developers/companies use WebRTC with NAT
         | Traversal.
         | 
         | You can also use it in a client/server setup. Check out 'WebRTC
         | SFU'
         | 
         | I wrote a little bit about the different topologies in [0]
         | 
         | [0] https://webrtcforthecurious.com/docs/08-applied-
         | webrtc/#webr...
        
       | jallmann wrote:
       | 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:
       | 
       | - Is this a full or partial state update?
       | 
       | - What if the client misses an update?
       | 
       | - What if the client loses connectivity?
       | 
       | - How can the server detect and clean up clients that have
       | disappeared?
       | 
       | How those are answered in turn raise more questions.
       | 
       | 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 _polling_ ) is
       | the clear winner.
        
         | apitman wrote:
         | This is one of my favorite articles along these lines:
         | 
         | https://blog.sequin.io/events-not-webhooks/
        
           | jallmann wrote:
           | Yeah that is a great article, and I agree that long polling
           | an events endpoint along with a cursor gets you most of the
           | way there for browser clients. At that point, things start to
           | resemble the Kafka protocol.
        
         | akira2501 wrote:
         | > Is this a full or partial state update?
         | 
         | It's a message. Mapping protocol units to messages was always
         | your business.
         | 
         | > What if the client misses an update?
         | 
         | Sequence numbers on updates combined with a "fill in" mechanism
         | through a separate request.
         | 
         | > What if the client loses connectivity?
         | 
         | Then more important things won't work either.
         | 
         | > How can the server detect and clean up clients that have
         | disappeared?
         | 
         | The SSE client will restart dropped connections. You can have
         | the server opportunistically close connections that haven't
         | received messages recently. The browser will automatically
         | reconnect if the object is still alive on the client side.
         | 
         | > For that, I would say that long polling (or even just
         | polling) is the clear winner.
         | 
         | Coordinating polling intervals while simultaneously avoiding
         | strong bursting behavior is genuinely not fun.
        
           | jallmann wrote:
           | All that speaks to the point that the underlying protocol
           | does not matter that much. The larger design is a more
           | important consideration than the specific push tech.
           | 
           | None of this favors SSE, or anything else for that matter.
           | You still have to think about bursting / thundering herd
           | behavior after server restarts, which would affect any
           | protocol. The browser auto reconnecting doesn't mean you can
           | assume the connection remains alive indefinitely if a
           | reconnect hasn't happened; you may want periodic
           | notifications as a keepalive to enable more immediate
           | recovery. Long-lived server state introduces its own
           | distributed coordination and cleanup problems, which strict
           | request-reply polling sidesteps entirely. Etc.
           | 
           | There is no silver bullet, only tradeoffs in the design space
           | that need to be matched to your application's requirements.
        
             | akira2501 wrote:
             | > the underlying protocol does not matter that much
             | 
             | Then why is long polling the "clear winner?"
        
               | jallmann wrote:
               | For interoperability with HTTP tooling (eg, curl) it is
               | the clear winner
        
       | tschellenbach wrote:
       | (I work at Stream, we power activity feeds, chat and video
       | calling/streaming for some very large apps)
       | 
       | 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.
       | 
       | WebTransport can have lower latency. If you're sending voice data
       | (outside of regular webrtc), or have a realtime game its
       | something to consider.
        
         | ambigious7777 wrote:
         | I'm making a WASM browser dungeon crawler game using
         | WebTransport. It currently does not have great support --
         | namely Safari -- but because of other API incompatibilities I'm
         | not planning on supporting Safari :P
         | 
         | WebTransport is a bit more work than other ones, like SSE, but
         | the flexibility and performance make it work it IMO.
        
       | cookiengineer wrote:
       | 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.
       | 
       | 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.
       | 
       | I've written an article from an implementer's perspective a while
       | ago, in case you are interested [1]
       | 
       | [1] https://cookie.engineer/weblog/articles/implementers-
       | guide-t...
        
       | atum47 wrote:
       | 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.
       | 
       | 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.
        
       | lxe wrote:
       | I love how SSE is just a "don't close the connection and just
       | keep flushing data". I bet IE6 supports this.
        
       ___________________________________________________________________
       (page generated 2024-03-18 23:01 UTC)