Server-Sent Events

by .

We’ve already had a glimpse at Server-Sent Events (also known as EventSource, and I’ll switch between the two to keep you on your toes) in my Methods of Communication article from last year. In this article, I want to delve in to more detail about the SSE API, demonstrate its features, and even show you how to polyfill browsers that lack EventSource support.

Server-Sent Events are real-time events emitted by the server and received by the browser. They’re similar to WebSockets in that they happen in real time, but they’re very much a one-way communication method from the server.

These events are similar to ordinary JavaScript events that occur in the browser — like click events — except we can control the name of the event and the data associated with it.

All the code for this article is available on github, and a live demo is available online.

† Is it Server-Sent Events or EventSource? Well, they both work. Server-Sent Events is the name of the API and specification. EventSource is the name of the JavaScript object you’re instantiating. It’s a bit like Ajax and XHR, where XHR refers to the XMLHttpRequest object…kinda.

Two notes: a) the uptime for this example is, I’m afraid, usually rather low — good for my server, bad for you. If you test the demo locally it will give you more interesting figures. b) IE6 isn’t supported in any of this article.

Possible Applications

A few simple examples of applications that could make use of Server-Sent Events:

  • A real-time chart of streaming stock prices
  • Real-time news coverage of an important event (posting links, tweets, and images)
  • A live Twitter wall fed by Twitter’s streaming API
  • A monitor for server statistics like uptime, health, and running processes

We’ll use the server monitor for this article’s examples. If this application were to be used in the wild, we could also check the EventSource‘s connection state to indicate when there’s a potential problem connecting to the server.

Overview of the API

The client-side API is rather simple, and it hands-down beats the insane hacks required to get real-time events to the browser back in the bad old days.

The main points of interest:

  • new EventSource(url) — this creates our EventSource object, which immediately starts listening for events on the given URL.
  • readyState — as with XHR, we have a readyState for the EventSource that tells us if we’re connecting (0), open (1), or closed (2).
  • onopen, onmessage — two events that we can listen for on the new EventSource object. By default, the message event will fire when new messages are received, unless the server explicitly sets the event type.
  • addEventListener — not only can we listen for the default message event, but we can also listen for custom messages using the addEventListener on the EventSource object, just as if we were listening for a click event.
  • event.data — as with most messaging APIs, the contents of the message reside in the data property of the event object. This is a string, so if we want to pass around an object, we need to encode and decode it with JSON.
  • close — closes the connection from the client side.

In the future, EventSource will also support CORS using an options argument to the EventSource object: { withCredentials: true }. But at the time of writing, no stable release includes this property.

Simple Example

Our simple web app will notify us of server status messages — things like the load average, number of currently connected users, and most CPU-intensive processes. If I were using this application in anger, I’d probably build server modules that emit specific event types when they cross specific thresholds, so that I’m only notified when something gets to warning level.

This snippet of JavaScript connects to our server, listens for messages, and handles the data that comes with the messages:

var source = new EventSource('/stats');
source.onopen = function () {
  connectionOpen(true);
};

source.onerror = function () {
  connectionOpen(false);
};

source.addEventListener('connections', updateConnections, false);
source.addEventListener('requests', updateRequests, false);
source.addEventListener('uptime', updateUptime, false);

source.onmessage = function (event) {
  // a message without a type was fired
};

Properties of Server-Sent Events

Server-Sent Events are more than just a one-way web socket. They have some unique features:

  • The connection stream is from the server and read-only. This suits lots of applications, some examples of which I listed above.
  • They use regular HTTP requests for the persistent connection, not a special protocol, which means we can polyfill using vanilla JavaScript.
  • If the connection drops, the EventSource fires an error event and automatically tries to reconnect. The server can also control the timeout before the client tries to reconnect.
  • Clients can send a unique ID with messages. When a client tries to reconnect after a dropped connection, it will send the last known ID. Then the server can see that the client missed n messages and send the backlog of missed messages on reconnect.

Message Format

A simple message doesn’t require much:

data: this is a simple message
<blank line>

Note that the end of a message is indicated by a blank line (obviously not the literal characters <blank line>).

For a message with multiple lines:

data: this is line one
data: and this is line two

You can send message IDs to be used if the connection is dropped:

id: 33
data: this is line one
data: this is line two

You can even send multiple messages in a single response so long as you separate the messages by blank lines:

id: 34
data: Remy is awesome

id: 35
data: Bruce is stinky

And you can specify your own event types (the above messages will all trigger the message event):

id: 36
event: price
data: 103.34

id: 37
event: news
data: Bruce sells his collection of replica bananas

You don’t have to worry about this structure on the client side. It only applies to the server, which I’ll touch on next.

Typical Server

I’m not going to give a full walkthrough of the server-side code, since this is an HTML5 web site :) But there are a few important and simple features that you need to know to build the server (you’ll need this part anyway if you’re going to use EventSource).

I’ve included all the files for this demo on GitHub for you to peruse at your own leisure, and I’ve also deployed a live example of this code.

Ideally, you should use a server that has an event loop. This means you should not use Apache, but instead use a platform such as Node.js (which I’ve used) or Twisted for Python.

Key properties:

  1. You can only accept EventSource requests if the HTTP request says it can accept the event-stream MIME type.
  2. You need to maintain a list of all the connected users in order to emit new events.
  3. You should listen for dropped connections and remove them from the list of connected users.
  4. You should optionally maintain a history of messages so that reconnecting clients can catch up on missed messages.

Here’s a sample of my Node.js based server. It’s using Connect (a simple webby framework for Node). When it receives a request for /stats, it calls the following function. I’ve commented the code so you can follow along:

function stats(request, response) {
  // only response to an event-stream if the request 
  // actually accepts an event-stream
  if (request.headers.accept == 'text/event-stream') {

    // send the header to tell the client that we're going
    // to be streaming content down the connection
    response.writeHead(200, {
      'content-type': 'text/event-stream',
      'cache-control': 'no-cache',
      'connection': 'keep-alive'
    });

    // support the polyfill - we'll come on to this later
    if (request.headers['x-requested-with'] == 'XMLHttpRequest') {
      response.xhr = null;
    }

    // if there was a lastEventId sent in the header, send
    // the history of messages we've already stored up
    if (request.headers['last-event-id']) {
      var id = parseInt(request.headers['last-event-id']);
      for (var i = 0; i < history.length; i++) {
        if (history[i].id >= id) {
          sendSSE(response, history[i].id, history[i].event, history[i].message);
        }
      }
    } else {
      // if the client didn't send a lastEventId, it's the
      // first time they've come to our service, so send an
      // initial empty message with no id - this will reset
      // their id counter too.
      response.write('id\n\n');
    }

    // cache their connection - the response is where we write
    // to send messages
    connections.push(response);

    // send a broadcast message to all connected clients with
    // the total number of connections we have.
    broadcast('connections', connections.length);

    // if the connection closes to the client, remove them
    // from the connections array.
    request.on('close', function () {
      removeConnection(response);
    });
  } else {
    // if the client doesn't accept event-stream mime type,
    // send them the regular index.html page - you could do
    // anything here, including sending the client an error.
    response.writeHead(302, { location: "/index.html" });
    response.end();
  }
}

The important trick on the server is to ensure you don’t close the connection to the EventSource object. If you do, it will of course handle the closed connection, fire an error event, and try to reconnect. So you’ll just want to maintain the persistent connection.

Polyfills and Tweaks to the Server

There are two good polyfills I know of, and though I prefer the one I wrote, I’ll still lay them both out for you.

Yaffle’s Polyfill

The first is one by Yaffle (on github), available on github/Yaffle/eventsource.

The cons:

  • It doesn’t send the accepts header, and
  • It completely replaces the EventSource object, so even if your browser supports EventSource natively, this script will replace it. But there’s a good reason for that.

The pros:

  • It maintains a persistent connection (whereas the one we’re using doesn’t), and
  • More interestingly, it supports CORS (which I imagine is why it replaces the native EventSource).

These two pros are quite compelling. But when I was testing, I couldn’t get it working in IE7 (which was my minimum browser target), so that might be a blocker for you…or not.

Remy’s Polyfill

The second is my own, available on github.com/remy/polyfills.

The cons:

  • It uses polling, so once a small group of messages come down, it re-establishes the connection, which could lead to significant overhead (though less so on a Node-based server). You have to add about 4 extra lines to your server code.

The pros:

  • It doesn’t replace the native EventSource object (but that also implies that, for now, it won’t support CORS), and
  • It supports IE7.

Retrospectively, I might choose Yaffle’s polyfill over mine in the future if I wasn’t bothered about IE7 support.

Using the Polyfill

By including the EventSource.js JavaScript library before my client-side code, I just need a couple of small changes to my server-side code. Other than that, everything on the client side works without any changes (as a polyfill should work).

When posting the server’s reply to the client, instead of keeping the connection open, I include the following in my server when it’s finished writing the response:

// send the data (event type, id, message, etc)
response.write(data);

// if our response contains our custom xhr property, then...
if (response.hasOwnProperty('xhr')) {
  // clear any previous timers using the xhr prop as the value
  clearTimeout(response.xhr);

  // now set a timer for 1/4 second (abritrary number) that
  // then closes the connection and removes itself from the
  // connection array.
  // The delay is in place so that a burst of messages can 
  // go out on the same connection *before* it's closed.
  response.xhr = setTimeout(function () {
    response.end();
    removeConnection(response);
  }, 250);
}

Bugs?

The error event should always fire when the readyState changes, assuming you didn’t explicitly call the close method. This works nearly all the time, but in writing this article, I found a few edge cases where it doesn’t fire. In Chrome, if I put my machine to sleep and then woke it back up, it would close the connection but not fire the event, therefore never triggering a reconnection. As I said, this is an edge case and I’ll file a bug against it, so I don’t expect it to hang around for long.

Why Not Use WebSockets?

There are two reasons I’d advocate using EventSource over WebSockets, as they’re currently the two contenders for sending real-time events to the browser.

The first is that EventSource (as we saw earlier) works over regular HTTP and can therefore be replicated entirely using JavaScript if it’s not available natively. That means that we can polyfill browsers without support, like IE9.

The second is probably more important: you should always use the right technology for the job. If your real-time data is sourced from your web site, and the user doesn’t interact in real-time, it’s likely you need Server-Sent Events.

I recently saw a cool demo of snowflakes drifting down a web site. Each snowflake is a tweet based around the Christmas theme — like if someone mentions a particular Christmas-y term, it’s sucked in to the snowflake. Don’t get me wrong, I know this is a demo, and it’s very cool (if you wrote it, this is me sending you hugs), but it’s based on WebSockets. I’d suggest this demo should be based on EventSource since all the data is read-only and the user doesn’t interact with it at all.

The point: evaluate the technology against your problem, and aim to get good fit.

53 Responses on the article “Server-Sent Events”

  • Motyar says:

    Great!! HTML5 is really nice, I can see a lot of possibilities.
    Not sure about few things. see this link says:-

    On the server-side, the script (“updates.cgi” in this case) sends messages in the following form, with the text/event-stream MIME type:
    data: This is the first message.

    Not sure How to write the API to “send” data, is it possible with PHP.

    Help needed!!

  • Remy Sharp says:

    @Motyar – it’s pretty straight forward to create a server with PHP, but you have to keep in mind that if PHP connection remains open (and you’re running a regular LAMP setup) then your server will eventually exhaust all of it’s connections.

    That aside, a simple PHP server can be seen over at Google’s HTML5 Rocks resource: http://www.html5rocks.com/en/tutorials/eventsource/basics/#toc-server-code

    Another important thing to note – which kinda defeats the points – is that apache and PHP will *close* the connection after the request. EventSource has no problem with this and re-opens the connection – but you’re effectively switching to Ajax polling because you’re using the wrong server side tech.

    Hope that helps.

  • BigAB says:

    I came for the strange things Remy and Bruce say:

    If I were using this application in anger…
    Bruce sells his collection of replica bananas

    …I left satisfied.

  • porneL says:

    Whys:

    * it’s much simpler to implement and debug. Protocol is dead simple and it’s all text. You don’t need huge server-side library or 3rd party service, you can just print the lines yourself.

    * it’s faster to connect (it’s just a regular HTTP request. No handshake or protocol negotiation) and protocol has less overhead (messages are not divided into frames/packets)

    * it’s HTTP-compatible, so it works with standard proxies (including nginx, Varnish, etc.), “corporate firewalls”, etc. Most 3G mobile networks force proxies on users, and WebSockets won’t work there without SSL.

    * browser handles resuming and error recovery automatically for you (and browser can do it well with awareness of the network interface, etc). That’s a surprisingly hard thing to get right from JS, and SSE gives that with 0 lines of code.

    * it can switch between permanent connection and polling at any time, so you can change strategy depending on your server load (e.g. if you run into connection limit, just drop some clients, they’ll reconnect in couple of seconds).

  • Mr C says:

    you should not use Apache, but instead use a platform such as Node.js

    if you are already forced down the route of node.js, you’d be daft not to use socket.io (which supports older browsers right out of the box). three lines of code and you have yourself a websocket server with ajax polling as a fallback.

    seems like SSE is a solution looking for a problem that someone else solved already.

  • Remy Sharp says:

    @Mr C – node is the example server I chose, you can use Juggernaut for Ruby, Twisted for python or Jakarta (I *think*) for Java.

    Equally I’d encourage you to consider the problem before just throwing Socket.IO at it. If you want bi-directional – then WebSockets and Socket.IO is perfect.

    If you want one way, Server Sent Events are perfect too. As you pointed out Socket.IO defers to polling. SSE is *not* polling by default – it automatically switches to polling if the connection is dropped. @porneL points out some excellent pros in favour of SSE too.

    But I’ll say it again: consider the problem, then apply the right solution to it. If SSE is being twisted to fit your problem – then clearly you’re going down the wrong avenue – and vice versa.

  • Mr C says:

    If you want one way, Server Sent Events are perfect too

    sure feels like momentum is elsewhere though – twitter returns links to this article but little else. you yourself were writing about websockets two years ago and SSE was available back then too.

  • Remy Sharp says:

    @Mr C – I don’t hold favour over either technology. I think both a very exciting. For example, as I write, I’m working on a project that actually need sever sent events – but because I must go cross domain, and using Ajax + iframes + postMessage + SSE is quite a long rope to jump, I’m electing to use WebSockets.

    It all goes back to the problem and the right fit for a solution.

  • Kai Hendry says:

    Last time I checked, SSE didn’t work on Android, so I was left with having to use socket.io IIRC. But I’m checking the demo on my Nexus S 2.3.6 and it works. Wow. :) Perhaps I was confused with another browser’s issue.

    Be better if it plotted connected clients overtime instead of load. :)

    I wish node was easier to host. I really don’t like it not running off :80, purely because it’s an eyesore. How do you manage the nodejs app.js process? In a /etc/init.d script? Upstart?

    Renting a VPS purely to run node sounds crazy.

    Wondering why you used connect over express.

    Nonetheless, great stuff. Keep it up!!

  • Zakaria says:

    Is there changes in web browser support since your last year article? (Opera 11, Safari, Mobile Safari and Chrome)

  • Nick Payne says:

    Fascinating stuff – as the author of said snowflake demo to whom you’re sending hugs, I have to hold my hands up and admit that this is the first time I’ve ever even heard of SSE. Definitely something to investigate further for those occasions where bidirectional support isn’t needed (I was going to say something like “though I can’t imagine many use-cases for that”, but that would sound a bit daft given my demo ;).

    Nick

  • Remy Sharp says:

    @Kai Hendry – SSE isn’t supported in Android 2.2 IIRC. But that was the reason why I could polyfill in using JavaScript and keep the properties of SSE rather than switching to polling. Yaffle’s polyfill might even be a better choice since it manages to retain the connection entirely whereas mine uses long polling.

    Also you mention the port number. Node *does* run on port 80, it just happens that the server I’m pointing you to is running multiple applications on it so I have them spread across multiple ports. It’s very easy to proxy in Node too (I just didn’t want to register a new domain just for this example). Here’s some examples I’ve written that run on port 80: http://jsconsole.com http://testyoursockets.com (sockets currently broken!) http://inliner.leftlogic.com and so on.

    Check out free hosting solutions like Heroku, nodester and the like.

  • Remy Sharp says:

    @Nick Payne – sorry for pointing you out – but I figured the pingback should (hopefully) get your attention that I’m sending you hugs for the code :)

    I was in the exact same position – I discovered native real-time tech a few years ago in the form of WebSockets, then over time discovered Server-Sent Events – and as I keep banging on, it’s using the right tool for the job. Anyway – nice work :)

  • Nick Payne says:

    @Remy not a problem at all – no apology required, and thanks for the mention (and the article!)

  • Alice Wonder says:

    I would appreciate some feedback as to whether or not server side events is the proper tool to what I am trying to accomplish.

    I have not written a single line of code yet, and I probably won’t for at least a few weeks, I have other unrelated stuff to button up first. But I’m thinking about it now.

    My server environment is CentOS 6.x running Apache, PostgreSQL, PHP (custom build, not stock) – I would not have any problems installing a different than apache http server to handle the SSE part, in fact, it might be nice to finally play with node.js. For my application, I don’t think database is going to be needed.

    What I am trying to build is a group chat client. Many would see that as bi-directional and thus web sockets, but my idea is to push the chat to the requesting clients regardless of whether or not they have participated or even picked a user name to participate with.

    You visit the chat page and start seeing responses as they happen from anyone in the room. You wish to participate, you choose a name and XMLHttpRequest checks it’s availability and if available your php session updated and you are good to go, if you choose to participate anything you write is sent by XMLHttpRequest and then shows up (for you and anyone else) when the server sends it as an SSE.

    I’d probably use php under apache to handle the username/login aspect and receive the XMLHttpRequest for clients sending the event but use node.js to send the chat posts as SSE.

    Am I barking up the wrong tree wanting to use SSE for this?

  • Kai Hendry says:

    @Alice AFAIK Apache and Node don’t place nicely, so if I were you I would dive into Socket IO and build your app out from there.

  • I prefer the Nginx Push Module (profile link). It’s more of a long-poll similar to IMAP IDLE, with a protocol specification that’s extremely clear on alternate implementations. E.g. I have one that integrates with my own C10K, HTTP/1.1 compliant, pure-Python web server.

    https://github.com/slact/nginx_http_push_module/blob/master/protocol.txt is the protocol RFC, less than 200 lines.

    https://github.com/slact/nginx_http_push_module/issues/43#issuecomment-3421412 describes one of the ways I’m using it.

  • Alice Bevan-McGregor says:

    @Kai You’re assuming I’m using Apache (nope, Nginx everywhere), Node (nope, Python everywhere), and need bidirectional low-latency communication (nope, could care less about client->server latency), and that my appS aren’t already stable and in production with their current Nginx/Python/Push architecture working great.

    Thanks for the suggestion, though! :)

  • Alice Wonder says:

    @KAI – My plan is to use Apache for everything EXCEPT the server sent events. Those would be sent by node.js either running on a different port or a different subdomain.

    Apache with php would manage everything else, including users sending messages to the group chat via XMLHttpRequest (parsing them for smileys, expanding shortened URLs like bit.ly, etc.) and then when ready to be sent to everyone connected, it would put the message in a cue to be eaten by the node.js server that sends them as a SSE.

    I could just do the whole thing in node.js but I prefer php programming and want the ability to have chat name match the username associated with the php session that is being used to access other parts of the web site. Using Apache/PHP for everything except sending of the SSE makes sense to me. Assuming SSE is the appropriate tech for plugin-less group chat.

  • Too many Alice’s here! :D

  • dhanesh mane says:

    hey thanks a lot, its really very nice article.

  • Boaz Brudner says:

    Thanks Remy! Great article.

    I have a question, I am planning on using server sent events to update clients on changes that occur on their own private data.

    For example email:

    I would like to notify each client that a new email has arrived for them and only notify them.

    Any recommendation on how I would go about implementing this?

    Is there a way for the web client to add a client id parameter in the EventSource (url)?

    Thanks
    Boaz

  • tiffany says:

    Another important thing to note – which kinda defeats the points – is that apache and PHP will *close* the connection after the request.

    You can get around these limits in PHP by using the sleep() function. That will will keep the connection open, BUT it will also extend the execution time of the script.

    My guess, however, is that this would not scale very well, particularly with Apache. It might work better with Nginx. I’ve only tried this on low-traffic URLs, myself.

  • Remy Sharp says:

    @tiffany it doesn’t scale. Here’s why: each client requires a persistent connection. Whilst php is sleeping, it’s resistant in memory. Let’s say php runs as 10Mb in memory. You’ve got a finite limit of persistent connections you can have before the machine tops out.

    That’s you need an event based server like Node.js or Twisted, and not php style servers.

  • Thaddee Tyl says:

    The reason most people say that websockets are a lot more logical to use is because socket.io exists. The API is so simple.

    What Server-Sent Events need is a similar module, with a simple API.

    I designed a such module. It is called camp. You can npm install camp it.

    Example of use: https://github.com/espadrine/sc/blob/master/app.js#L33

    Those two lines demo a chat server.

  • Dinesh says:

    In the above example which is like this,

    id: 36
    event: price
    data: 103.34

    id: 37
    event: news
    data: Bruce sells his collection of replica bananas

    How do we get both the id’s 36,37 on the server side?Can anyone please tell me.

  • Val says:

    I don’t understand why could we not have the very first line of a javascript file (inline or external) using Yaffle’s method.

    `if (EventSource!==’undefined’)
    var __event_source = EventSource`

    so instead of doing new `new EventSource(‘blabla’)` could be `new__event_source(‘blabla’)` why should this be a disadvantage?

    I guess what I am saying is, you create an alias of the event source object before Yaffle’s has a chance to override it… and most importantly, if it has been overridden it’s usually for the best, unless he is a fool.

  • Remy Sharp says:

    @Val – simply because eventually you want to remove the polyfills. If your code uses

    new __event_source('blah')

    it will completely fail when you remove the polyfill.

    This way you happily rely on the browser providing you standards.

    Your version would also draw confusion in years to come if someone else had to support it. They’d see

    __event_source

    rightly deciding this wasn’t the real EventSource object and have to go looking for what it actually is – then only to find it’s an alias…and if that’s the point in time where you don’t need the polyfill, they’ll assume you’re the fool for aliasing the object.

    Point being: code to the web standards, and polyfill where they’re not available, allowing your code to remain exactly as it should be.

  • Henri says:

    Installation tip for Remy’s nodejs sse server:

    use Connect version 1.x. The current master branch of Connect is incompatible with the sse server code.


    npm install connect@1.x

  • FZambia says:

    Thanks very very much for this article! It helped me a lot!

    I have written SSE broadcasting server on python using cyclone web server (tornado clone on top of twisted). You can find it on github: https://github.com/FZambia/cyclonehttps://github.com/FZambia/cyclone-sse-sse

  • Andy says:

    Hi, I have a quick question. (I am new to web development so this may be trivial or may not make any/much sense, still ..)

    How much and how fast can we send data from server to client using server sent events. My requirement is to send 25kb or so every 20 milliseconds.

    Please reply.

  • Andy says:

    Forgot to say I am using tomcat … java at server side and javascript at client side … I understand this depends on network and hardware as well … but assuming everything is on same machine .. or so … what will be the bottle neck from server sent event side or http .. if any

  • vrobbi says:

    My contribution to this tecnology is here:

    http://www.nuovoweb.eu/index1.php

    Also there is an example of web notification, another html5 feature

  • Erika Rendon says:

    I am trying to build a chat application into my site. I want to build it myself for the experience. I was considering doing it in NODE.JS but now I am serious think about going with SSE. Does anyone know if this is a wise choice? I am looking for someone that has done this in the past and can speak from experience.

  • Alice Bevan-McGregor says:

    @Erika Rendon — When implementing new things I usually start at the simplest and work up.

    A long time ago on this article I commented about the Nginx HTTP Push Module which follows the Basic HTTP Push Relay protocol. I have since used it to implement a complete async push online multiplayer board game with lobbies, in-game chat, spectators, and spectator chat. Total development time: two hours. (One for the async part, the second for game logic.) The prototype only required Nginx (no other server-side software) and in the final project proposal estimated that 1 million simultaneous active games (ignoring chat) would only require 801MB of RAM and would consume about 18GB of bandwidth total.

    My jQuery adapter for NHPM is available via the linked GitHub Gist. This version is slightly more formalized as a generic async JSON packet transceiver.

    (Obviously for security a production system would need a real back-end endpoint for the clients to POST messages to; exposing the raw publish URLs to the wild wild web would be a Bad Thing™.)

  • Remy Sharp says:

    [edit] – see @kll’s reply below mine (I’ve kept my originally reply, but kll is right, and it does indeed make sense to use SSE based on their ideas).

    [original comment]

    @Erika my feeling is you really want web sockets, rather than SSE (both technologies are well suited to node.js based servers).

    Since chat is real-time in both directions and SSE is only messages *from* the server, it doesn’t quite match solving chat.

    Hope that’s of help.

  • kll says:

    @Erika @Rem: I think chat is *the perfect* use case for SSE, and a very poor fit for WebSockets.

    In a chat app you don’t send messages 60 times per second! WebSockets have advantage only if you send lots of messages continuously.

    But in a chat app you only POST a message once in a while, and plain old AJAX is perfect for that.

    So you can have server-sent-events for receiving messages in real time from the server, and client-sent-AJAX for sending the messages.

    And chat app is for general use, so it’s better to have wider compatibility and lower overhead of SSE rather than pay for complexity of WebSockets.

  • Remy Sharp says:

    @kll – well said – and yep, put that way, I totally reverse my recommendation.

  • Chris says:

    Remy,the method in app.js using connect.createServer to get app,now app is a Server object.But the latest connect API changed,app have no ‘use’ method.Here is the update from npm’s connect page:

    var connect = require(‘connect’)
    , http = require(‘http’);

    var app = connect()
    .use(connect.favicon())
    .use(connect.logger(‘dev’))
    .use(connect.static(‘public’))
    .use(connect.directory(‘public’))
    .use(connect.cookieParser())
    .use(connect.session({ secret: ‘my secret here’ }))
    .use(function(req, res){
    res.end(‘Hello from Connect!\n’);
    });

    http.createServer(app).listen(3000);

    Just let you know,maybe someone else got the same problem.

  • simon says:

    this article is the best article i have seen about sse.
    to be honest, it is much better then html5rocks’s tutorial.
    i’d like to say that remy is very thoughtful and experienced.

  • Bruno says:

    Really nice post. I was looking for a clean explanation of SSE on both client and server for a while. +1 for the clean Polyfill.

    On the discussion about the ‘chat’ use case for SSE, I have to agree with @kkl on the asymetry between the clients and the server: while the server is constantly pushing messages from possibly thousands of users, the client only sends a message once in a while. Despite being a bidirectional conversation, there is a huge gap between the load generated by the client and the load generated by the server.

    But what if we think about an IRC like app? One can start a private conversation with another user and here we would expect symetry.

    Again about an IRC like app, what if we would allow users to create their own chatroom and other users could join him in a public domain-specific conversation.

    How would one test for performance using both websockets and SSE? I’m thinking about doing this study in node.js, but still no idea on how I would go to benchmark both technologies.

  • Anon says:

    Hi Remy,

    A very good article! Thank you.

    By the way, this all is JavaScript (SSE, WebSockets etc…), isn’t it? Why is it classified under HTML5 specifically?

  • Jack says:

    Hi,
    I am just discovering SSE, and I like very much your approach “the right thing for the right usage”. Your post is enlightning.
    I am bulding an app on node, and so far I am with socket.io. It’s a kind of “giant” chat.
    I am more and more concerned about potential limits on the number of concurrent users with node & socketio, which is critical for me.

    Have you experienced any limitation of concurrent connections with SSE ?
    thx
    /Jack

  • Alexander Popov says:

    Great article. The link to the live demo doesn’t wok.

  • Abdul Jabbar says:

    Just one word for all “PERFECT” for teaching step by step but was even more better if we could find some example with Apache as well because Apache is still highly used for PHP specially. And yes your demo link is also not working :(

  • XIE JIABAO says:

    I create a servlet class for sse using JAVA. If I want each client have own connection of sse, how should I do?
    How to do like that – maintain a list of all the connected users in order to emit new events?

  • Viktor says:

    @XIE JIABAO, possibly, it is better to use async sockets from java nio, you can mantain a list of client sockets

  • DNA says:

    I can’t seem to find any articles on configuring Apache on AWS EC2 Linux instance so that PHP Server Sent Events can be used simultaneously with forms which can receive a POST request from the server. Can this be done? and if so how could I accomplish this?

  • ritu says:

    I am trying to use Jersey SSE between a JAVA client and a Java rest service implementation.
    When we close the eventSource on from client side no event gets triggered from the server side.I need to do soen clean up activity but unfortunately I am not able to catch this event.
    It would be great if you could give some suggestions around this.

  • i doing Remote Monitoring System project …
    Here i m using SSE for checking Online or offilne of system using severSocket program in java

    i’m geting output no problem in that but when i was Refresh the page or Moving Some Other Page and come back the page its not working but in console i m geting output … the On Source Message Event is not working When u Refresh please Help me Im Staked…
    below i Given My code

    if (typeof (EventSource) !== “undefined”) {
    var i=0;
    source = new EventSource(“http://localhost:8080/RemoteLoingServerfinalz/Done1”);

    source.onmessage = function(event) {

    alert(event.data);

    };
    } else {
    document.getElementById(“ServerTime”).innerHTML = “Sorry, your browser does not support server-sent events…”;
    }

  • sime says:

    Looks like Yaffe’s polyfill doesn’t override Firefox and Chrome’s native implementation: https://github.com/Yaffle/EventSource/commit/1b85c03bff8fdb534550b61f65ca762a7c9c6731

  • Leave a Reply to Nick Payne

    Some HTML is ok

    You can use these tags:
    <a href="" title="">
    <abbr title="">
    <b>
    <blockquote cite="">
    <cite>
    <del datetime="">
    <em>
    <i>
    <q cite="">
    <strong>

    You can also use <code>, and remember to use &lt; and &gt; for brackets.