Hacker Newsnew | past | comments | ask | show | jobs | submitlogin
Server-sent events (developer.mozilla.org)
136 points by corentin88 on May 15, 2023 | hide | past | favorite | 104 comments


I know alot of websites and engineers use Websocket for push only data. SSE is tailored made for real time one sided updates!

In fact, I think it made a better chat protocol, when we built a chat system at a previous job, similar to Slack. We ended up leveraging SSE to push updates to channels and traditional HTTP requests to send data to the server, resulting in lower latency and less overhead on the server side. We did this because we found the following to be true:

- At any given time, there are far more people reading chat messages than writing them

- What matters is that updates after being sent to everyone else is that their pretty close to instantaneous but you had a 500ms window to allow for the server to receive a new message and then propagate it out. Therefore, for the sender, you update the UI optimistically so they aren't waiting for a response, and everyone else will get it in ~500ms and its imperceptible

- one downside: its harder (we never figured it out before I left) to do indicators for when someone is typing. That really does seem to require two way real time connections


The big problem i've run into with SSE is the connection limit [1]:

> Warning: When not used over HTTP/2, SSE suffers from a limitation to the maximum number of open connections, which can be specially painful when opening various tabs as the limit is per browser and set to a very low number (6). The issue has been marked as "Won't fix" in Chrome and Firefox. This limit is per browser + domain, so that means that you can open 6 SSE connections across all of the tabs to www.example1.com and another 6 SSE connections to www.example2.com. (from Stackoverflow). When using HTTP/2, the maximum number of simultaneous HTTP streams is negotiated between the server and the client (defaults to 100).

The natural way to use SSE is to create an EventSource on each page. If you do this, and your user opens six tabs, they can now no longer make HTTP requests to your site. Not just SSE requests, any HTTP requests at all!

It's also quite natural, i think, to want to use multiple separate streams. It's very convenient to write separate endpoints for various kinds of data that a page might want, for example one for streaming numerical data, one for control messages, and one for descriptive events; or one for each panel on a dashboard. Here, you can hit the limit on a single page.

I wrote a thin layer over my HTTP server's APIs which lets me write a single handler which can send events via either SSE or a websocket. Then, when i build a page, i use websockets, but if i want to debug, i can still use curl to make a normal HTTP request. Also, other apps can use SSE to pull data, which only requires an HTTP client, not a websocket client.

[1] https://developer.mozilla.org/en-US/docs/Web/API/EventSource


> The natural way to use SSE is to create an EventSource on each page. If you do this, and your user opens six tabs, they can now no longer make HTTP requests to your site. Not just SSE requests, any HTTP requests at all!

You can use EventSource in a singleton worker and use postMessage to forward messages to all open browser tabs for the same origin.


SharedWorker (the thing needed for a "singleton worker") only just made it into Safari the end of last year...

plus you now have to handle multiplexing and demultiplexing for different tabs on both server and client.

By the time that arrived and HTTP/2 had wide enough adoption, everyone's already used to building atop Websocket...

Also the EventSource in the browser is heavily gimped. GET only, No custom headers, and last I checked you can forget about configuring any CORS stuff for credential passing.


Not sure if that's what you are asking but there's a `withCredentials` option (which IIRC is the only possible option)

I was looking at : https://stackoverflow.com/questions/61041389/managing-server...

Shared worker would actually allow for SSE in a service worker ! That's nice.


The original comment stands: it's harder.


This SO answer seems to say that it wouldn't work : https://stackoverflow.com/questions/61041389/managing-server...

If you have an answer to that answer I'd be very much interested


You can use BroadcastChannel [1] to communicate between tabs. It works well and does not require service workers. It's used in Tracim [2], for some reason we could not move to HTTP/2 at the time I was working on this project so we indeed learned about this connection limit soon enough…

Even on HTTP/2, I believe it's best avoid sending 6 times the same message to the user just because they opened 6 tabs. It's less wasteful both for the server and the client.

[1] https://developer.mozilla.org/en-US/docs/Web/API/BroadcastCh...

[2] https://github.com/tracim/tracim/blob/develop/frontend_lib/s...


Thanks very much for the examples ! I get your point but it does seem quite more involved to do all that management and broadcasting by hand rather than having a shared worker with a EventSource singleton for all, don't you think ? : https://stackoverflow.com/a/61636606/10469162

EDIT: Someone posted this very relevant and interesting post : https://greenvitriol.com/posts/browser-leader


EventSource is bad. We were using it to connect to GPT 4 via our server acting as a middleware (we hosted the code for returning the LLM response on our server since our company's OpenAI API key is supposed to be private).

However, previous developers had written a basic middleware to check if a req.body exists and if it contains a userId (since our server was handling multipler other things apart from this one component of the business logic).

However, any such manipulation of the request body isn't possible with EventSource (and I felt that using a workaround such as passing the userId in the querystring could cause some security issue), so I ended up using the fetch() method to connect to our server for interacting with GPT 4.


In short, it reads to me as "HTTP/2 or don't bother".

Not an unreasonable requirement for a serious modern web app.


Yes, but weirdly enough the most popular javascript for handling http, express, does not support HTTP2 ! Fastify does


> It's also quite natural, i think, to want to use multiple separate streams.

i dont think i'd call it natural per se - i'd say it's just "easy" to do so, and especially if each of these separate streams are managed by different teams, and it makes business sense to separate the responsibility.

There should be a framework, perhaps, to allow "multiplexing" of multiple streams of events into one actual tcp connection. Of course, this requires some work, but i dont think it's actually that much extra work. It just needed to be planned out as a need, as it might be a tad hard to tack it on after the fact (tho that's not impossible either).


Just create more subdomains if you really need more sockets.

Or move away from the browser. Browsers are toxic now.


One major issue I encountered with SSE is dealing with reconnection. WebSocket makes it very easy to detect differences between a loss of network connectivity, a server dying, and a client exiting properly (eg: closing the tab), on either side of the socket.

Maybe there are facilities to do so with SSE that I don't know of, but my experience in reliable server-to-client-only comms with it has been a bit rough.


This also matters for load balancers. With SSE or chunked encoding long polling, it's possible to lose the client connection without the load balancer closing the connection to the server, at least for a while.

WebSockets make it easy to do periodic heartbeats from the server, which puts an upper bound on how long a client connection can be in an uncertain state.

This also enables client presence data, even if the client only ever receives messages.


You pretty much just have to listen for and handle premature closing of the underlying TCP connection. It's the only form of dead peer detection you'll get if someone just abrubtly closes their browser tab.


Do server frameworks really require you to think of the TCP connection?


Not TCP specifically, but ASP.NET Core binds your controller/action methods' CancellationToken parameter (if present) to HttpContext.RequestAborted - so assuming one uses it correctly (e.g. tying it to things like SQL TRANSACTION/ROLLBACK) then that helps prevent inadvertent changes if the user clicked their browser's Stop button after a POST, or gracefully handle long file upload failures, and so on.


High performance servers and frameworks will always have to think about the underlying sockets


I don't think I understand. Both WebSockets and server-sent events are just a long lived TCP socket, right? Why would SSE be lower overhead? Why wouldn't it be more overhead to go through the whole HTTP request handling machinery for EVRY chat message everyone sends? You already have an underlying 2-way connection in the TCP socket, why not use it?

And why would latency be lower with HTTP requests + SSE than with websockets?


It's not. SSE has higher overhead and there are browser limits as to how many concurrent channels a single client can consume. Also, SSE encourages you to shift complexity to the back end where it would be more appropriate on the front end.

For example, the client knows which channels it needs, so why not let the client decide which channels to subscribe to over a single WebSocket connection? With SSE, you end up having to do this channel management and keep track of which user is associated with what SSE connections on the back end since the user cannot just open any number of new channels on-demand (due to limits in number of concurrent SSE connections; it's better to multiplex over a single SSE connection). If your system runs on multiple processes or hosts, figuring out which process/host a particular user is connected to is a nightmare and forces you to create clients on the back end to aggregate messages for specific users and then publish to the correct SSE connection which uses extra memory and exposes your server to potential DoS vulnerabilities. It creates the need for a bunch of complex user-connection-matching and cleanup logic on the back end and it complicates access control.

I have no idea why this "let's micromanage data streams for each user individually on the back end" approach became so popular while the alternative approach of end-to-end pub/sub is rarely used when it results in a much simpler, more secure system.

With end-to-end pub/sub, you can multiplex multiple channels over a single bidirectional connection in a way which conveniently and cleanly allows you to couple multiple subscriptions over that single WebSocket connection... No complex cleanup on the back end on disconnection, no risk of stale channels on the back end, no need to poll for user activity to check for subscription liveness. As soon as the WebSocket is disconnected, the client can be fully unsubscribed from all their channels on the server-side.


In NestJs it is quite easy to manage in the backend, there's a SSE decorator for you SSE service and then you just return an observable on a subject. (See RxJs) Sending message events sends to all observers on the subject and when the `observed` property` becomes false, you just close the connection.


Slack does use websocket for “someone is typing” event: https://slack.engineering/real-time-messaging/


What was the challenge in typing indicators? My naive idea is that it's basically sending `typing_started` and `typing_ended` messages.


You can skip the "typing ended". You're gonna need a shortish timeout anyway, may as well just let the "typing is happening" messages all terminate by timeout.


That really depends on the UX you want.


What do you have in mind? I can't think of a case where you'd want "X is typing" to persist more than a second or maybe two past the last-received message that affirmed X is, in fact, still typing. I can think of cases in which a short timeout might break down in bad ways (making the notice really jittery on high-latency connections, say) but I think those are probably just situations in which any "... is typing" message is simply gonna be bad in one way or another.


You don't want to clear it after only a second. It should persist much longer since people pause and think between words.

It's common that someone starts typing but immediately change their mind and clears the input after only a couple of characters. So if the timeout is longer you need an "ended" event.


(the "ended" event is the message being sent.)


Except for the scenario the parent is talking about:

> It's common that someone starts typing but immediately change their mind and clears the input after only a couple of characters.


I'm guessing that since it's not a full-duplex connection you have to send those messages out-of-band, ie, with a separate POST request API


But messages themselves are already sent out-of-band as a POST request, if I understand correctly. Don't see why that couldn't be extended to include typing indicators.


I used both WebSockets and SSE. In one project, I even support WebSockets and a fallback working like what you describe.

I'm sold on using SSE for pushed updates. But how is regular requests + SSE easier on the server compared to WebSockets? It seems like an open connection to maintain in both cases plus additional http request for the SSE+requests case.


You need to multi-thread your server on shared memory to build many-to-many solutions. The simplest way to get that working is Java + NIO with concurrent package, I have done it for you: http://github.com/tinspin/rupy

My web server outperforms everything on the planet for multiplayer.

Websockets are notoriously hard to parallelize if you want shared memory which you need for many-to-many, mostly because JavaScript and C++ have very poor atomic concurrency, or atleast I never found any Websocket server that could do it.


> You need to multi-thread your server on shared memory to build many-to-many solutions

Not necessarily, it depends on the needs, but in any case I would not expect SSE and WebSockets to be different in this regard.

I'm not sure what's specifically hard to parallelize with WebSockets. Shared memory may be hard to handle but that does not seem specific to WebSockets which are just regular two way communication channels that happen to start with an HTTP request from the client.


Websockets use one TCP socket for starters with SE you use separate sockets from ingress and egress which is much simpler to scale from an infrastructural point of view.

I clearly said many-to-many, everything else is trivial to scale because only many-to-many requires strictly shared memory atomic parallelization.

You could write a better server in Java than javascript/c(++) but I haven't found any, and to be honest the extra complication of the binary protocol doesn't even make me curious enough to waste 5 seconds to google it.

SSE over HTTP/1.1 is the final solution. Everything else is a waste of time for eternity.


Server Sent Events infamously have low global connection limit per origin[1], so if you have multiple tabs open for a single site you'll run into it pretty quickly. If it weren't for that, they would be great.

[1] https://stackoverflow.com/questions/18584525/server-sent-eve...


That's just over HTTP/1. For HTTP/2 (which most people should be using anyway), the limit is 100.


I've never worked with Web Workers, but the doc page mentions them at the very top. Isn't that the intended workaround? Have a background thread that receives the events & coordinates, rather than having each page deal with them?


Yes, that's `ShardedWorker`.


I wanted so use these in a project recently, only to find out that they aren't supported on Chrome for Android. This makes them non-usable for me, since there is no drop-in polyfill available yet.


If you are doing websocket in there, you could fall back to main thread, but it comes at the cost of code duplication.


You can do leader election[1] in that case

[1] https://greenvitriol.com/posts/browser-leader


Sophisticated services that offer SSE will have many different endpoint domains to get around browser limits on simultaneous connections to the same service.

endpoint-00.example.com endpoint-01.example.com endpoint-02.example.com

etc. It isn't specific to SSE. It's any HTTP request. SSE is just the most obvious because the connections stay open for long periods.


That's what I'm saying: it's not that good for non-sophisticated services, you need workarounds to make this "great technology" work. Might as well switch to websockets and not worry about this.


Another "workaround" is to enable HTTP/2, which should be already enabled if the system is managed by a competent admin who cares about his work.


Right, but with websockets you wouldn't have to think about this at all.

You'd also need to ensure http2 for local development, proxies in between, etc. You _can_ do all this, but you can also avoid putting any thought into this matter.


And that's an easy workaround, with wildcard DNS entries and certs.


This problem is fixed by using HTTP/2.


No, the browser's HTTP connection limits still apply on HTTP2, each `EventSource` per tab counts against this limit of I think 6 (?) connections.

Websockets to my knowledge have no such limit because they are not HTTP requests.


This is simply not true, it's negotiated between the client and server and defaults to 100 usually. 6 is the limit for http 1.1 not http/2.

Source: https://developer.mozilla.org/en-US/docs/Web/API/Server-sent...


I believe you have it essentially backward. Websockets consume a connection no matter what, as the protocol does not work with HTTP2 (there was an attempt, but I believe it wasn't adopted and abandoned).

The SSE requests do work with HTTP2, as do some other old methods like long polling. All the tabs will generally share one connection to that domain.


> Websockets consume a connection no matter what, as the protocol does not work with HTTP2 (there was an attempt, but I believe it wasn't adopted and abandoned).

Are you thinking of RFC 8441? https://www.rfc-editor.org/rfc/rfc8441

If so, then it's already implemented by Firefox: https://bugzilla.mozilla.org/show_bug.cgi?id=1434137

...and by Chrome/Chromium since 91: https://chromestatus.com/feature/6251293127475200


Thanks. Last time I checked I still saw them consuming connections, but I suppose that's probably the far end not supporting it.


My favorite use of this that I've spotted in the wild is https://nightride.fm (not affiliated, just a fan!). It's a Synthwave music site + community.

In particular, I noticed that EventSource goodies are used to broadcast currently playing songs on each station, as well as to provide anon read access to their IRC server via a simple vanilla javascript webapp.

WAY cleaner and easier than web sockets for this use case, and CDN friendly to boot!


Note that this really isn’t anything except the agreement to send messages separated by 2 new lines. The SSE object in browsers is old and quirky; for example, it only supports GET requests, which means you’ll hit path length limits if you use it for something like LLM completion with large prompts.

Luckily since there’s nothing special about the browser support, you can very easily replace it with custom implementations. https://www.npmjs.com/package/@microsoft/fetch-event-source for example offers mostly the same API, but does offer POST requests and a bunch of other goodies.


There is this agreement, and also the fact that browsers can forget previous messages, unlike any xhr-based custom implementation since the EventSource object does not provide methods to access previous contents. I don't know how well this package handles this.

I agree with the note about the auto retry mechanism of EventSource. It does no good, is unavoidable and a big annoyance. The work we had to do to work around it in Tracim (previous job) [1] was pure madness. I see this part has not been touched since I left by the way.

https://github.com/tracim/tracim/blob/develop/frontend_lib/s...


This seems like a great solution for streaming responses scoped to a single request. Neat!

I've always used SSEs to open a more persistent comms channel to a browser which creates way more state and complexity both on the client and the server.


I was looking through the implementation of chat.openai.com recently and was pleasantly surprised to see that it was 100% Server Sent Events, no Websockets.

SSE is a great tool to have in your belt. I'd say it can replace the majority of use cases for Websockets out there today (basically pushing small amounts of text/JSON data to the client) with a tiny fraction of the complexity. Opening and maintaining a bidirectional TCP stream is otherwise a huge pain in the ass.


SSE is pretty good but I have never been able to see the messages in firefox devtools, and doesn't work with binary data.

HTTP/2 streams are just as easy to implement, and work both ways and support binary data.


Try debugging HTTP/2 on a live machine when you have 10.000 concurrent users and get back to me how well you sleep.

console.log or wireshark


I love SSE.

I fear years back I made a Monopoly Deal game with a client-server arch.

Server was in Go with SSE, and client was in JS/Svelte with SVG and a lot of CSS.

It work so so well ! The clientside cmds (like "place this card there") was vanilla ajax send to Go Server, but the "state" was always send via SSE to connected clients.

I was surprised to see how far Joe Average (Yea I use bootstrap for most things) can push CSS for nice looking card game.

PS: Oops I mean "WildDeal" not "Monopoly Deal", no need to get sued


Was it a side project of yours ? Mind sharing a link ?


I took it down, was like 95% done but ran out of motivation to make it bullet-proof and catch all the corner cases. Also needed to add something like WebRTC, we found out playing with my friends we always were in a Zoom/Jitsi/WhatsApp call with each other, half the fun is the "vocal banter" :D

Wait Wait do you work for "Hasbro" :O ?

PS - Fun Nerd Fact: Hasbro owners of many many board games including monopoly also owns the trademark for "Ouija Board" (yea the spirits phone-home one) :D


Love to see stuff like this on the HN front page, when I know tons of web devs that have never even heard of SSE.

Tangentially, I’m having a massive problem with SSE datastreams erroring out about two minutes in for “ERR: Network chunk encoding” reasons, anyone else seen this before?


Has there been traffic during that two minutes?

In theory, a TCP session can remain alive forever. In practice, various things got in the way, and you need traffic to keep it alive (keep-alive, ping, heartbeat, it gets given various names). I believe once a minute should be enough. I’ve encountered "ping" and "" used as SSE event names for this purpose.


Try sending the messages without compression. A lot of servers don't know how to handle this for SSE (since its a uncommon content type)


You need to send "keep-alive" "noop" to keep the routers happy, I do it ever 5 seconds.


See I tried that, still issues. Wondering if it is just a problem with internal firewalls and routing rules


Try the connection from other server + client locations.


“Operator, please keep this line clear!”


I'm a little confused by how this is used. The trivial example provided on developer.mozilla.org is a PHP script that's fully self-contained. As far as I could tell, a self-contained PHP script doesn't provide much value. I would have expected something to happen on the server, like a database record getting updated, which triggers the PHP to send an SSE message to the browser, but how do you trigger that particular PHP instance to send a message? Does the PHP instance just poll the database on a periodic basis? That doesn't seem much better than having the browser poll the web server on a periodic basis...


> That doesn't seem much better than having the browser poll the web server on a periodic basis...

It could indeed be much better for performance. It means the polling happens over a (presumably) low-latency, high-throughput local datacenter connection, and not over the end-user's internet connection over which you have no control.

But more importantly, SSE only defines the interface between the web browser and web server. Rather than polling a DB, you could just as well hook the web server up to a more sophisticated pubsub system (although PHP might not be the best choice for that). In that regard, SSE is no different from websockets; the main difference is that it's a simpler protocol to implement, and only works one-way.


Ah, the part that was missing from my mental map was having the PHP instance act as a subscriber in a pubsub system. Thanks!


You could have some kind of event system running that pushes the event down to php. For instance, redis has a PUBSUB system, and postgresql has NOTIFY.


Ah, the part that was missing from my mental map was having the PHP instance act as a subscriber in a pubsub system. Thanks!


SSE are amazing! I've used them to push updates to clients from multiple goroutines (Go threads) with https://lastfm.live

It's quite simple to start with on the Go backend side of things and the frontend things aren't too complicated either.


For my fellow high-IQ individuals initially confused by the seeming lack of content in the article, it's under 'Guides': https://developer.mozilla.org/en-US/docs/Web/API/Server-sent...

A bit easy to miss, but includes some actual code samples and a really nice walkthrough. Highly encouraged even if you already "know" SSE and want to solidify your knowledge, I like how it doesn't hide any of the details.


Curious why is this trending? Btw sse are pretty great, only thing I don't get is why they don't allow for binary payloads. That'd have been the icing on the cake.


> only thing I don't get is why they don't allow for binary payloads

I've always appreciated that it's just a simple line-oriented UTF-8 text protocol. Binary transfers are handled more efficiently with something else. Or just base64 the payload if it's not that big of a deal.


This got into the zeitgeist somehow. I just implemented my first SSE app with FastAPI last week, then I saw a youtube video and this post!

I was implementing something with websockets and asked chatgpt to tell me about modern alternatives. In my years of full-stack… I hadn’t heard of SSE, or at least never got why I should care.

Damn, I see the limitations of REST, but I was building state machines and custom protocols with websockets. It’s nice to prototype in REST again.

REST+SSE ftw, I guess!


String parsing is never the bottleneck. You need to parallelize (shared memory) and understand your system and for that text is pretty convenient.

So also avoid HTTPS.

It's trending because it's the final real-time solution for eternity.



OP here. I was looking at Anthropic's website as a result of https://news.ycombinator.com/item?id=35948742

Turns out in their FAQ, they have this:

> Our API is designed to be a backend that incorporates Claude into any application you’ve developed. Our application sends text to our API, then receives a response via *server-sent events*, a streaming protocol for the web. We have API documentation with drop-in example code in Python and Typescript to get you started.

Was curious what it was and thought it was probably worth sharing.

Didn't knew OpenAI uses the same mechanism.


My first thought was ChatGPT API's `stream` option: https://platform.openai.com/docs/api-reference/completions/c...


OpenAI uses this in their APIs to stream tokens


I did a web app project with SSEs a while back. They worked well in the browser, but when it came time to build a mobile app (React Native), I had trouble finding a good library to use. I'm sure I could have rolled my own, but being in a time crunch I ended up using Firebase Cloud Messaging. Hopefully there's better support these days.



ChatGPT uses SSE to stream the AI's responses, token-by-token!


Not really related, but this is GAE's missing feature IMO


I wish there were a way to push not just anonymous data/events but http resources, to similar effect.

SSE & websockets & http streams can send anonymous data, but I'd like to be able to send an actual thing. As per the most core architecture of the web:

> Axiom 0a: Universality 2. Any resource of significance should be given a URI. https://www.w3.org/DesignIssues/Axioms.html#uri

Or alternatively,

> Cool URLs don't change (implicitly, cool things have URLs, see above). https://www.w3.org/Provider/Style/URI

Instead of pushing to a chat app an anonymous blob of json for a chat message to a room, the server could assert a /room/42/msg/c0f3 resource, could identify universally what it is it's sending. The advantage would be so high. It'd become a standard way to assert a resource, to make known a fact, that would be viable across systems. Further http requests to the resource would just work. Folks could link to the resource. How cool it would be if we could send not just data but resources?

We have come glancingly close to getting such a thing so many times. The HyBi mailing list that begat websockets had a number of alternate more resourceful ideas floating around such as a BEEP protocol that allowed patterns beyond request/response of resources. The browser actually implements an internal protocol that uses HTTP2/push to send resourceful messages, web push protocol/RFC8030, https://datatracker.ietf.org/doc/html/rfc8030.

But the underlying http2/push was de-implemented for webserving in general, and even when it was available, it lacked the oft requested ability to get notice of new pushed resources. (https://github.com/whatwg/fetch/issues/65 was an old request. https://github.com/whatwg/fetch/issues/607 had some steam in making it happen.) Tragic backwards moves in my view, and never acknowledged by blink-dev when protests arose.

The best we have today is to stream json-ls events, which have an @id property identifying them. But developers would have to snoop these events, and store them in a service worker, to make them actually accessible as http resources.

I continue to hold hope eventually we'll get better at using urls to send data, to assert new things happening... But it's been nearly 30 years of me hoping, and with some fleeting exceptions the browser teams have seemed disinterested in making urls cool, in spite of a number of requests. We've been left at un-web side-channels like SSE & Websockets for a long long time now. Wouldn't it be nice to see some real growth for http capabilities that we really can use, that are more than abstract underlying transport tweaks like h2 and h3?


How well do these work out in practice across a variety of platforms, behind firewalls, on phones, and so on?


They're well supported on modern browsers, both mobile and desktop. If you need to support IE then you can use a polyfill. It's essentially just a long-running HTTP request. The main issue I've run into before is if your server has a response timeout configured then you'll need to disable or work around it, otherwise it will disrupt the event stream whenever the timeout is hit, since the event stream is just an HTTP response.


They work EVERYWHERE except through some very rare buggy anti-viruses and ISP implementations.

Real life stats: "759 out of 205.875 customers refunded because their antivirus blocks the pull HTTP stream", so 99.7%!

They even go through the great firewall without bureaucracy.


I use this at work (Enterprise SAAS web software) and we had to implement a backup "polling every 5 seconds" for clients that would not support it. It's quite rare though. We assume that some caching proxy might be waiting for the GET request to be fully done to cache it and then give it to the user or something like this. The SSE would then never get updates, while every normal HTTP request would work


I've read that this does indeed happen with some HTTP proxies. In some environments that includes HTTPS because some environments intercept HTTPS traffic too. It's enough for me to consider SSE too unreliable to use if my application needs to be reliable with events, and it's the first thing I thought when I saw the SSE spec the first time.

Back beore SSE, I recall seeing some server-to-client event protocol specification inserted extra padding bytes after events in the middle of an HTTP response stream, just to convince some HTTP proxies to forward the event in an incomplete HTTP response, but I don't recall which protocol now. It was never entirely clear how much padding would be enough, or if any amount would be.

When cometd and the Bayeux publish-subscribe protocol was designed, this is why long-polling was always used, instead of streaming partial responses inside a single HTTP response. With correctly designed overlapping long-polling requests, it's possible to get event latency very similar to SSE, without this issue of lost events due to proxies. So that's a good, reliable choice, if you don't use WebSockets. In fact it's more reliable than WebSockets (which can also get stuck at some proxies), so if you value very reliable event delivery long-polling or just periodic polling are the way to do it, but with much higher overhead.

In theory SSE provides the option for mobile device power saving described at https://html.spec.whatwg.org/multipage/server-sent-events.ht... Using more active protocols almost certainly defeats this. In theory a mobile network and network stack (modified inside the mobile browser where cleartext is available) could implement that power saving strategy for mostly-idle WebSockets too, which is another argument for WebSockets.


SSE is phenomenal and underutilized because it wasn't supported by IE.


It wasn't "not supported" they had a bug that they never could fix because it would have broken 50% of the internet.

Be careful what you release because it might not be fixable after release.


What is the advantage of SSE over streaming ndjson?


Built-in client API for parsing and event dispatching. Data doesn't have to be JSON encoded.

But fundamentally nothing that Comet, steaming XHR, etc, WebSockets, can't do.


A streaming XHR is more wasteful in that it constantly has to renegotiate TLS. This is unlike EventSources and WebSockets, which do not.


?

Why do you believe that?


Because that's how the protocol works at a fundamental level. If you're making new requests over HTTP, you have to renegotiate TLS.




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: