TE
TechEcho
Home24h TopNewestBestAskShowJobs
GitHubTwitter
Home

TechEcho

A tech news platform built with Next.js, providing global tech news and discussions.

GitHubTwitter

Home

HomeNewestBestAskShowJobs

Resources

HackerNews APIOriginal HackerNewsNext.js

© 2025 TechEcho. All rights reserved.

Server-Sent Events (SSE) Are Underrated

338 pointsby Igor_Wiwi5 months ago

31 comments

kdunglas5 months ago
A while ago I created Mercure: an open pub-sub protocol built on top of SSE that is a replacement for WebSockets-based solutions such as Pusher. Mercure is now used by hundreds of apps in production.<p>At the core of Mercure is the hub. It is a standalone component that maintains persistent SSE (HTTP) connections to the clients, and it exposes a very simple HTTP API that server apps and clients can use to publish. POSTed updates are broadcasted to all connected clients using SSE. This makes SSE usable even with technologies not able to maintain persistent connections such as PHP and many serverless providers.<p>Mercure also adds nice features to SSE such as a JWT-based authorization mechanism, the ability to subscribe to several topics using a single connection, events history, automatic state reconciliation in case of network issue…<p>I maintain an open-source hub written in Go (technically, a module for the Caddy web server) and a SaaS version is also available.<p>Docs and code are available on <a href="https:&#x2F;&#x2F;mercure.rocks" rel="nofollow">https:&#x2F;&#x2F;mercure.rocks</a>
评论 #42512565 未加载
评论 #42511826 未加载
评论 #42520302 未加载
评论 #42513202 未加载
dugmartin5 months ago
It doesn’t mention the big drawback of SSE as spelled out in the MDN docs:<p>“Warning: When not used over HTTP&#x2F;2, SSE suffers from a limitation to the maximum number of open connections, which can be especially painful when opening multiple tabs, as the limit is per browser and is set to a very low number (6).”
评论 #42512171 未加载
评论 #42512145 未加载
评论 #42511669 未加载
评论 #42511993 未加载
评论 #42513246 未加载
评论 #42513027 未加载
评论 #42511577 未加载
piccirello5 months ago
I utilized SSE when building automatic restart functionality[0] into Doppler&#x27;s CLI. Our api server would send down an event whenever an application&#x27;s secrets changed. The CLI would then fetch the latest secrets to inject into the application process. (I opted not to directly send the changed secrets via SSE as that would necessitate rechecking the access token that was used to establish the connection, lest we send changed secrets to a recently deauthorized client). I chose SSE over websockets because the latter required pulling in additional dependencies into our Golang application, and we truly only needed server-&gt;client communication. One issue we ran into that hasn&#x27;t been discussed is HTTP timeouts. Some load balancers close an HTTP connection after a certain timeout (e.g. 1 hour) to prevent connection exhaustion. You can usually extend this timeout, but it has to be explicitly configured. We also found that our server had to send intermittent &quot;ping&quot; events to prevent either Cloudflare or Google Cloud Load Balancing from closing the connection, though I don&#x27;t remember how frequently these were sent. Otherwise, SSE worked great for our use case.<p>[0] <a href="https:&#x2F;&#x2F;docs.doppler.com&#x2F;docs&#x2F;automatic-restart">https:&#x2F;&#x2F;docs.doppler.com&#x2F;docs&#x2F;automatic-restart</a>
评论 #42511810 未加载
评论 #42511801 未加载
apitman5 months ago
&gt; Perceived Limitations: The unidirectional nature might seem restrictive, though it&#x27;s often sufficient for many use cases<p>For my use cases the main limitations of SSE are:<p>1. Text-only, so if you want to do binary you need to do something like base64<p>2. Browser connection limits for HTTP&#x2F;1.1, ie you can only have ~6 connections per domain[0]<p>Connection limits aren&#x27;t a problem as long as you use HTTP&#x2F;2+.<p>Even so, I don&#x27;t think I would reach for SSE these days. For less latency-sensitive and data-use sensitive applications, I would just use long polling.<p>For things that are more performance-sensitive, I would probably use fetch with ReadableStream body responses. On the server side I would prefix each message with a 32bit integer (or maybe a variable length int of some sort) that gives the size of the message. This is far more flexible (by allowing binary data), and has less overhead compared to SSE, which requires 7 bytes (&quot;data:&quot; + &quot;\n\n&quot;) of overhead for each message.<p>[0]: <a href="https:&#x2F;&#x2F;stackoverflow.com&#x2F;a&#x2F;985704" rel="nofollow">https:&#x2F;&#x2F;stackoverflow.com&#x2F;a&#x2F;985704</a>
评论 #42513283 未加载
评论 #42512410 未加载
Tiberium5 months ago
One thing I dislike regards to SSE, which is not its fault but probably a side effect of the perceived simplicity: lots of developers do not actually use proper implementations and instead just parse the data chunks with regex, or something of the sorts! This is bad because SSE, for example, supports comments (&quot;: text&quot;) in streams, which most of those hand-rolled implementations don&#x27;t support.<p>For example, my friend used an LLM proxy that sends keepalive&#x2F;queue data as SSE comments (just for debugging mainly), but it didn&#x27;t work for Gemini, because someone at Google decided to parse SSE with a regex: <a href="https:&#x2F;&#x2F;github.com&#x2F;google-gemini&#x2F;generative-ai-js&#x2F;blob&#x2F;main&#x2F;src&#x2F;requests&#x2F;stream-reader.ts#L28">https:&#x2F;&#x2F;github.com&#x2F;google-gemini&#x2F;generative-ai-js&#x2F;blob&#x2F;main&#x2F;...</a> (and yes, if the regex doesn&#x27;t match the complete line, the library will just throw an error)
recursivedoubts5 months ago
<a href="https:&#x2F;&#x2F;data-star.dev" rel="nofollow">https:&#x2F;&#x2F;data-star.dev</a> is a hypermedia-oriented front end library built entirely around the idea of streaming hypermedia responses via SSE.<p>It was developed using Go &amp; NATS as backend technologies, but works with any SSE implementation.<p>Worth checking out if you want to explore SSE and what can be achieved w&#x2F;it more deeply. Here is an interview with the author:<p><a href="https:&#x2F;&#x2F;www.youtube.com&#x2F;watch?v=HbTFlUqELVc" rel="nofollow">https:&#x2F;&#x2F;www.youtube.com&#x2F;watch?v=HbTFlUqELVc</a>
评论 #42515548 未加载
评论 #42515530 未加载
deaf_coder5 months ago
The part where it says:<p>&gt; SSE works seamlessly with existing HTTP infrastructure:<p>I&#x27;d be careful with that assumption. I have tried using SSE through some 3rd party load balancer at my work and it doesn&#x27;t work that well. Because SSE is long-lived and doesn&#x27;t normally close immediately, this load balancer will keep collecting and collecting bytes from the server and not forward it until server closes the connection, effectively making SSEs useless. I had to use WebSockets instead to get around this limitation with the load balancer.
评论 #42516049 未加载
评论 #42516437 未加载
评论 #42542656 未加载
评论 #42516214 未加载
hamandcheese5 months ago
I tried implementing SSE in a web project of mine recently, and was very surprised when my website totally stopped working when I had more than 6 tabs open.<p>It turns out, Firefox counts SSE connections against the 6 host max connections limit, and gives absolutely no useful feedback that it&#x27;s blocking the subsequent requests due to this limit (I don&#x27;t remember the precise error code and message anymore, but it left me very clueless for a while). It was only when I stared at the lack of corresponding server side logs that it clicked.<p>I don&#x27;t know if this same problem happens with websockets or not.
评论 #42512179 未加载
评论 #42512197 未加载
RevEng5 months ago
OpenAI&#x27;s own documentation makes note of how difficult it is to work with SSE and to just use their library instead. My team wrote our own parser for these streaming events from an OpenAI compatible LLM server. The streaming format is awful. The double newline block separator also shows up in a bunch of our text, making parsing a nightmare. The &quot;data:&quot; signifier is slightly better, but when working with scientific software, it still occurs too often. Instead we&#x27;ve had to rely on the totally-not-reliable fact that the server returns each as a separate packet and the receiving end can be set up to return each packet in the stream.<p>The suggestions I&#x27;ve found online for how to deal with the newline issue are to fold together consecutive newlines, but this loses formatting of some documents and otherwise means there is no way to transmit data verbatim. That might be fine for HTML or other text formats where newlines are pretty much optional, but it sucks for other data types.<p>I&#x27;m happy to have something like SSE but the protocol needs more time to cook.
评论 #42526776 未加载
ramon1565 months ago
They&#x27;re underrated when they work™<p>Currently at work I&#x27;m having issues because - Auth between an embedded app and javascript&#x27;s EventSource is not working, so I have to resort to a Microsoft package which doesn&#x27;t always work. - Not every tunnel is fond of keep-alive (Cloudflare), so I had to switch to ngrok (until I found out they have a limit of 20k requests).<p>I know this isn&#x27;t the protocol&#x27;s fault, and I&#x27;m sure there&#x27;s something I&#x27;m missing, but my god is it frustrating.
评论 #42512473 未加载
_caw5 months ago
&gt; SSE works seamlessly with existing HTTP infrastructure<p>This is false. SSE is not supported on many proxies, and isn&#x27;t even supported on some common local proxy tooling.
anshumankmr5 months ago
SSE is not underrated. In fact it&#x27;s being used by Open AI for streaming completions. It&#x27;s just not always needed unlike the very obvious use cases for normal REST APIs and Websockets.<p>It was a pain to figure out how to get it to work in a ReactJS codebase I was working on then and from what I remember Axios didn&#x27;t support it then so I had to use native fetch to get it to work.
评论 #42516105 未加载
schmichael5 months ago
I’ve never understood the use of SSE over ndjson. Builtin browser support for SSE might be nice, but it seems fairly easy to handle ndjson? For non-browser consumers ndjson is almost assuredly easier to handle. ndjson works over any transport from HTTP&#x2F;0.9 to HTTP&#x2F;3 to raw TCP or unix sockets or any reliable transport protocol.
评论 #42511915 未加载
cle5 months ago
&gt; Automatic Reconnection<p>I wouldn&#x27;t characterize this as &quot;automatic&quot;, you have to do a lot of manual work to support reconnection in most cases. You need to have a meaningful &quot;event id&quot; that can be resumed on a new connection&#x2F;host somewhere else with the Last-Event-Id header. The plumbing for this event id is the trivial part IMO. The hard part is the server-side data synchronization, which is left as an exercise for the reader.<p>Also, God help you if your SSE APIs have side effects. If the API call is involved in a sequence of side-effecting steps then you&#x27;ll enter a world of pain by using SSE. Use regular HTTP calls or WebSockets. (Mostly b&#x2F;c there&#x27;s no cancellation ack, so retries are often racy.)
programmarchy5 months ago
Great post. I discovered SSE when building a chatbot and found out it’s what OpenAI used rather than WebSockets. The batteries-included automatic reconnection is huge, and the format is surprisingly human readable.
upghost5 months ago
Does anyone have a good trick for figuring out when the client side connection is closed? I just kill the connection on the server every N minutes and force the client to reconnect, but it&#x27;s not exactly graceful.<p>Secondly, on iOS mobile, I&#x27;ve noticed that the EventSource seems to fall asleep at some point and not wake up when you switch back to the PWA. Does anyone know what&#x27;s up with that?
评论 #42513350 未加载
评论 #42512153 未加载
wlonkly5 months ago
I love the format of this. I can tuck it away and whenever I need to think about SSE, refer back to it, ah, okay, now I&#x27;m all caught up.<p>Also, surprised nobody&#x27;s brought up PointCast[1] yet. Dotcom bubble, or ahead of their time?<p>(Aside: while looking for a good reference link for Pointcast, I found an All Things Considered episode[2] about it from 1996!)<p>[1] <a href="https:&#x2F;&#x2F;www.ecommerce-digest.com&#x2F;early-dot-com-failure-case-studies.html#:~:text=Pointcast.Com" rel="nofollow">https:&#x2F;&#x2F;www.ecommerce-digest.com&#x2F;early-dot-com-failure-case-...</a><p>[2] <a href="https:&#x2F;&#x2F;www.npr.org&#x2F;1996&#x2F;02&#x2F;13&#x2F;1042379&#x2F;pointcast" rel="nofollow">https:&#x2F;&#x2F;www.npr.org&#x2F;1996&#x2F;02&#x2F;13&#x2F;1042379&#x2F;pointcast</a>
henning5 months ago
They are handy for implementing simple ad-hoc hot reloading systems as well. E.g. you can have whatever file watcher you are using call an API when a file of interest changes that sends an event to listening clients on the frontend. You can also trigger an event after restarting the backend if you make an API change by triggering the event at boot time. Then you can just add a dev-only snippet to your base template that reloads the page or whatever. Better than nothing if your stack doesn&#x27;t support it out of the box and doesn&#x27;t take very much code or require adding any additional project dependencies. Not as sophisticated as React environments that will only reload a component that changed and only do a full page refresh if needed, but it still gives a nice, responsive feeling when paired with tools that recompile your backend when it changes.
lakomen5 months ago
No they&#x27;re not. They&#x27;re limited to 6 clients per browser per domain on http&#x2F;1.1 Which is important because nginx can&#x27;t reverse proxy http&#x2F;2 or higher, so you end up with very weird functionality, essentially you can&#x27;t use nginx with SSE.<p><a href="https:&#x2F;&#x2F;developer.mozilla.org&#x2F;en-US&#x2F;docs&#x2F;Web&#x2F;API&#x2F;Server-sent_events&#x2F;Using_server-sent_events#sect1" rel="nofollow">https:&#x2F;&#x2F;developer.mozilla.org&#x2F;en-US&#x2F;docs&#x2F;Web&#x2F;API&#x2F;Server-sent...</a><p>Edit: I see someone already posted about that
yu3zhou45 months ago
I&#x27;ve had no idea they exist until I began to use APIs serving LLM outputs. They work pretty well for this purpose from my experience. An alternative to SSE is web sockets for this purpose I suppose
aniketchopade5 months ago
I had some trouble implementing when server has to wait for another endpoint (webhook) to feed output to browser . During request processing (thread1) had to store the sse context in native Java object which will be retrieved later when webhook(thread2) is called But then with multiple service instance you wouldn&#x27;t know which service had stored it so webhook had to publish something which others has to subscribe.
est5 months ago
I built several internal tool to tail logs using SSE with Flask&#x2F;FastAPI. Easy to implement and maintain.<p>For FastAPI if you want some hooks when client disconnects aka nginx 499 errors, follow this simple tip<p><a href="https:&#x2F;&#x2F;github.com&#x2F;encode&#x2F;starlette&#x2F;discussions&#x2F;1776#discussioncomment-3207518">https:&#x2F;&#x2F;github.com&#x2F;encode&#x2F;starlette&#x2F;discussions&#x2F;1776#discuss...</a>
ksajadi5 months ago
I&#x27;m curious as to how everyone deals with HTTP&#x2F;2 requirements between the backend servers and the load balancer? By default, HTTP&#x2F;2 requires TLS which means either no SSL termination at the load balancer or a SSL cert generated per server with a different one for the front end load balancer. This all seems very inefficient.
评论 #42513184 未加载
评论 #42513259 未加载
fitsumbelay5 months ago
Finding use cases for SSE and reading about others doing the same brings me great joy. Very easy to set up -- you just set 2 or 3 response headers and off you go.<p>I have a hard time imagining the tech&#x27;s limits outside of testing scenarios so some of the examples brought up here are interesting
junto5 months ago
This is why SignalR in .NET land is so popular in that ecosystem. It automatically falls back to SSE if web sockets aren’t available. In essence giving totally transparent real time communication.
sbergjohansen5 months ago
Previous related discussion (2022):<p><a href="https:&#x2F;&#x2F;news.ycombinator.com&#x2F;item?id=30403438">https:&#x2F;&#x2F;news.ycombinator.com&#x2F;item?id=30403438</a> (100 comments)
benterix5 months ago
The topic is interesting but the ChatGPT style of presenting information as bullet points is tiring.
Tiberium5 months ago
Also, another day, another mostly AI-written article on HN&#x27;s top page :)
评论 #42512097 未加载
评论 #42513926 未加载
whatever15 months ago
Can Django with vanilla gunicorn do this ?
评论 #42514047 未加载
crowdyriver5 months ago
http streaming is even more underrated.
condiment5 months ago
So it’s websockets, only instead of the Web server needing to handle the protocol upgrade, you just piggyback on HTTP with an in-band protocol.<p>I’m not sure this makes sense in 2024. Pretty much every web server supports websockets at this point, and so do all of the browsers. You can easily impose the constraint on your code that communication through a websocket is mono-directional. And the capability to broadcast a message to all subscribers is going to be deceptively complex, no matter how you broadcast it.
评论 #42511553 未加载
评论 #42511549 未加载