Say Goodbye to WebSockets? Why SSE Might Be Your New Best Friend
zakaria chahboun

zakaria chahboun @zakariachahboun

About: i'm zakaria chahboun, i'm a software engineer ♥ i'm also a designer and i'm a voice actor in arabic language.

Location:
morocco in agadir city
Joined:
Jan 9, 2020

Say Goodbye to WebSockets? Why SSE Might Be Your New Best Friend

Publish Date: Feb 11
249 51

Introduction

Hey fellow devs! 👋 Today, let's dive into Server-Sent Events (SSE) and explore why they might be your next favorite tool for real-time communication. If you've been relying on traditional request-response methods or wrestling with WebSocket complexity, SSE might be the simpler solution you've been looking for!

Table of Contents

What are Server-Sent Events?

SSE is a standard that enables servers to push real-time updates to clients over a single HTTP connection. Think of it as a one-way communication channel where your server can send updates whenever it wants, without the client having to ask for them repeatedly.

Key Benefits

1. Low Latency for Real-Time Updates

Imagine you're building a chat app. Instead of your users constantly asking "any new messages?" (polling), the server can instantly push new messages to them.

2. Efficient Resource Usage

No more polling! The server only sends data when there's actually something new to share.

3. Simpler than WebSockets

While WebSockets are powerful, SSE uses standard HTTP and is much simpler to implement.

4. Built-in Reconnection

Lost connection? No worries! SSE automatically handles reconnection for you.

SSE Message Format

Before we jump into the code, let's understand the SSE message format. The server sends messages in this format:

event: myevent    // Optional: name of the event
data: message     // The actual message content
id: 123          // Optional: event ID for resuming connection
retry: 10000     // Optional: reconnection time in milliseconds

Enter fullscreen mode Exit fullscreen mode

Each field must end with a newline (\n), and the message must end with two newlines (\n\n).

Simple Code Examples

Backend (Go)

package main

import (
    "fmt"
    "net/http"
    "time"
)

func sseHandler(w http.ResponseWriter, r *http.Request) {
    // Set headers for SSE
    w.Header().Set("Content-Type", "text/event-stream")
    w.Header().Set("Cache-Control", "no-cache")
    w.Header().Set("Connection", "keep-alive")

    // Check if the ResponseWriter supports flushing
    flusher, ok := w.(http.Flusher)
    if !ok {
        http.Error(w, "Streaming unsupported", http.StatusInternalServerError)
        return
    }

    // Sending events every second
    for i := 0; i < 10; i++ {
        // Write SSE event format
        fmt.Fprintf(w, "event:welcome\ndata: Message %d\n\n", i)

        // Flush the response to send the event immediately
        flusher.Flush()

        // Simulate a delay
        time.Sleep(time.Second)
    }
}

func main() {
    http.HandleFunc("/events", sseHandler)
    fmt.Println("Server listening on :8080")
    http.ListenAndServe(":8080", nil)
}
Enter fullscreen mode Exit fullscreen mode

Key Points:

  • w.Header().Set("Content-Type", "text/event-stream"): Ensures the client treats this as an SSE connection.
  • w.Header().Set("Cache-Control", "no-cache"): Prevents caching of the SSE stream.
  • w.Header().Set("Connection", "keep-alive"): Keeps the connection open for continuous

Frontend (JavaScript)

// Basic SSE connection
const eventSource = new EventSource('http://localhost:8080/events');

// Handle regular messages
eventSource.onmessage = (event) => {
    console.log('Received message:', event.data);
    document.getElementById('messages').innerHTML += `<p>${event.data}</p>`;
};

// Handle named events
eventSource.addEventListener('welcome', (event) => {
    console.log(event.data);
});

// Handle connection open
eventSource.onopen = () => {
    console.log('Connection opened!');
};

// Handle errors
eventSource.onerror = (error) => {
    console.log('Error occurred:', error);
};

// To close connection when needed
function closeConnection() {
    eventSource.close();
}
Enter fullscreen mode Exit fullscreen mode

SSE vs WebSockets: When to Use What? 🤹

While both SSE and WebSockets are used for real-time communication, here’s a quick comparison:

Feature SSE WebSockets
Communication One-way (server to client) Two-way (bi-directional)
Setup Complexity Simpler (works over HTTP) More complex (requires WebSocket protocol)
Client Support Well-supported by modern browsers Supported in most modern browsers
Use Case Ideal for notifications, live feeds, data updates Ideal for chat, multiplayer games, full-duplex communication
Reconnection Automatic reconnection built-in Must handle reconnection manually

Best Use Cases for SSE 🎯

  1. Live notifications
  2. Real-time dashboards
  3. Stock market updates
  4. Social media feeds
  5. Live sports scores
  6. System monitoring

Pro Tips 💡

  1. Message Types: You can send different types of events:
   // Regular message
   data: Your message here\n\n

   // Named event
   event: userconnected\n
   data: John joined\n\n

   // Multiple data lines
   data: line 1\n
   data: line 2\n\n
Enter fullscreen mode Exit fullscreen mode
  1. Reconnection Control: Set custom retry time:
   retry: 5000\n\n
Enter fullscreen mode Exit fullscreen mode
  1. Event IDs: Track message sequence:
   id: 12345\n
   data: Your message here\n\n
Enter fullscreen mode Exit fullscreen mode
  1. Full Example: All SSE Properties:
   event: notification\n
   data: Payment is successful\n
   retry: 5000\n
   id: transaction-id-12345\n\n

   event: notification\n
   data: Shipping update: Your package has been dispatched\n
   retry: 5000\n
   id: shipping-id-98765\n\n
Enter fullscreen mode Exit fullscreen mode

Conclusion 🎉

SSE is a powerful yet simple tool for real-time updates. It's perfect when you need server-to-client updates without the complexity of WebSockets. The built-in features like automatic reconnection and the simple HTTP-based protocol make it a great choice for many real-time applications.

Have you used SSE in your projects? What has been your experience? Let me know in the comments below! 👇


Happy coding! 🍉

Comments 51 total

  • OssiDev
    OssiDevFeb 11, 2025

    It's amazing that I've been at this for 15+ years and I'm still discovering new things like server-sent events. It was proposed 20 years ago already and somehow I've missed it completely. Simply never bumped into it.

    Thanks for this post!

    • zakaria chahboun
      zakaria chahbounFeb 12, 2025

      Glad this post brought it to your attention! Do you think you'll use SSE in any of your projects?

  • Mike Talbot ⭐
    Mike Talbot ⭐Feb 11, 2025

    A warning: you're probably going to still need some kind of polling fallback. These days I check for receipt acknowledgement and then use the SSE stream for polling, which works, but the server has to close the connection if it doesn't get an "ack".

    • KUNDAN KUMAR
      KUNDAN KUMARFeb 12, 2025

      True. I am still struggling to configure nginx properly for SSE

      • Mike Talbot ⭐
        Mike Talbot ⭐Feb 12, 2025
        res.set({
                "Content-Type": "text/event-stream",
                "Cache-Control": "no-cache, no-store, must-revalidate",
                Pragma: "no-cache",
                Expires: "0",
                "Transfer-Encoding": "chunked",
                Connection: "keep-alive",
                "Access-Control-Allow-Origin": process.env.ORIGIN || request.get("origin") || "*",
                "X-Accel-Buffering": "no",
            })
        
        Enter fullscreen mode Exit fullscreen mode

        These are the headers I send

    • zakaria chahboun
      zakaria chahbounFeb 12, 2025

      Cool, thanks for sharing! I will read it. 🙏

  • Code With Sushil
    Code With SushilFeb 12, 2025

    thanks man

  • Athreya aka Maneshwar
    Athreya aka ManeshwarFeb 12, 2025

    Pretty solid, btw how did you create the blog image?

  • Kalapee Gajjar
    Kalapee GajjarFeb 12, 2025

    Okay more seaport to back and

  • Naveen Kumar
    Naveen KumarFeb 12, 2025

    Few days back, we got a requirement where our DAO layer is collecting data from some files in the backend, as now this data can be large and we cannot load the complete data in memory hence we thought of going with SSE where server can send the data in chunks to Client in stream without loading the complete data.
    In this case also SSE played a good role to send the data continuously without waiting to load in memory at once.

    Websocket can be also used for this purpose but here we dont want duplex channel hence SSE played a vital role.

  • Elanza-48
    Elanza-48Feb 12, 2025

    The title of the post is very misleading. You might get excited when you learn new things that doesn't mean "Saying goodbye to something", just for views don't do such nonsense.

    • zakaria chahboun
      zakaria chahbounFeb 12, 2025

      Not everything has to be taken so seriously—sometimes a catchy title is just that. Take it easy!

      • John Watts
        John WattsFeb 12, 2025

        Click bait is always click bait.

  • rslhelper
    rslhelperFeb 12, 2025

    witching from WebSockets to SSE sounds like a big shift! SSE’s simplicity and lower overhead make it a strong alternative, especially for real-time updates. Curious to see how it holds up in high-demand applications!

  • Richard William
    Richard WilliamFeb 12, 2025

    It all began with a sinking feeling in the pit of my stomach. I had invested $152,000 in what I thought was a promising cryptocurrency venture, only to realize too late that it was a sophisticated scam.  I felt like I had lost everything—my hard-earned money, my confidence, and my hope, I tried everything I could think of to recover my funds. I reached out to the platform’s support (which no longer existed), But every door I knocked on seemed to lead to a dead end. The world of cryptocurrency, with its anonymity and decentralization, felt like a labyrinth designed to keep me trapped in my loss, as I scoured the internet for any glimmer of hope, I stumbled upon Dexdert Net Pro. At first, I was skeptical. I had seen countless recovery services promising to retrieve lost funds, only to discover they were scams themselves. But something about Dexdert Net Pro felt different. Their website was professional, their team was transparent, and they had a track record of success stories that seemed genuine. Desperate I  decided to take a chance,  I reached out to Dexdert Net Pro and explained my situation. To my surprise, they responded quickly and with genuine empathy. Their team of experts, specializing in blockchain technology and cyber investigations, took the time to understand the details of my case. They asked for all the relevant information—transaction records, communication with the scammers, and any other evidence I could provide,   Dexdert Net Pro worked tirelessly on my case. Throughout the process, they kept me informed, providing regular updates and answering my questions with patience and clarity, Dexdert Net Pro successfully recovered my lost Bitcoin. I couldn’t believe it. The $152,000 I thought was gone forever was being returned to me. The relief and gratitude I felt were overwhelming. Dexdert Net Pro had not only reclaimed my funds but also restored my faith in the possibility of justice in the digital age,  I realize how fortunate I was to find Dexdert Net Pro,  Their expertise, dedication, and integrity turned what seemed like an impossible situation into a story of redemption. If you ever find yourself in a similar predicament, I can’t recommend Dexdert Net Pro enough. They truly are the best in the business.

    Email:(DexdertNetPro@mail.com) Telegram:(@Dexdertprorecovery)

  • jothish
    jothishFeb 12, 2025

    It's just a brodcaster?
    How the authorisation works here?
    If there is 100 users , everyone will get everyones data??
    I'm sorry I'm just a noob trying new things

    • Troy High
      Troy HighFeb 12, 2025

      @5p4r70n , you would have to use your existing auth model. For example, we use sse to send notifications to users of our system when they are in the admin console. The app uses tokens so the server only receives authenticated messages.

      Also since we have info on the user via the token we store some identifier info on the cached connection pool so when a SSE is generated we can send only to clients that match the recipient id.

    • peerreynders
      peerreyndersFeb 12, 2025

      SSE is simplest described as a regular HTTP request with a streaming response; the streaming payload is events.

      • The server closing the response is unexpected, so the client sends another request to start again.
      • The client will close the connection when it is done with the request.

      WS requests on the other hand convert (“upgrade”) the HTTP request to something outside of the HTTP spec to get access to the sockets that the original HTTP request was using.

      In both cases the server has to manage a distinct connection to each user; however SSE connections tend to be less demanding on server resources and SSE may work where WS won't; like when firewalls block non-HTTP traffic. But both require an always-on server,so neither of them is suitable for a serverless environment.

      • jothish
        jothishFeb 12, 2025

        Ok, go it

        The server and client will keep this connection alive for future server-to-client event notifications.

        Thanks! 😊

    • zakaria chahboun
      zakaria chahbounFeb 12, 2025

      Great questions! SSE isn't just a broadcaster—it's a way for the server to push updates to clients in real-time over a single HTTP connection.

      As for authorization, it usually works by validating the user's identity before establishing the SSE connection, just like any other secure connection.

      // Sends a GET request to /events
      const eventSource = new EventSource('/events', {
          headers: {
              'Authorization': 'Bearer your_token_here'
          }
      });
      
      // Or Cookies
      const eventSource = new EventSource('/events', {
          withCredentials: true // Ensures cookies and credentials are sent with the request
      });
      
      Enter fullscreen mode Exit fullscreen mode

      The server responds with an HTTP response that has a Content-Type: text/event-stream header and keeps the connection open to send multiple events over time.

      Regarding your last question: If you have 100 users, each client will only receive the data that the server sends to it. Typically, you would send specific updates based on the user’s permissions or the data they’re subscribed to, so not everyone gets everyone else's data.

  • Andrew Rhyand
    Andrew RhyandFeb 12, 2025

    Using SSE as been a new pattern for me. After using tools like HTMX, I feel in love with sending back fragments of HTML.

    Then I found Datastar data-star.dev/

    It's a blend of JS signals, HTMX, and SSE.

  • АнонимFeb 12, 2025

    [deleted]

    • Dan Jones
      Dan JonesFeb 13, 2025

      Wow. An AI-generated comment about AI-generated content.

  • Dylan Westraadt
    Dylan WestraadtFeb 12, 2025

    SSE has a limit of 6 connections per browser window. Just something to keep in mind. Its not a one size fits all solution.

    • peerreynders
      peerreyndersFeb 12, 2025

      It's 6 connections (i.e. requests, not just SSE) per domain across the entire browser for HTTP/1.x. The limit is a lot higher for HTTP/2.

      That said architecturally the plan would be to multiplex all traffic over a single SSE for the entire page and for an MPA to use leader election where only one page of the domain would use an SSE and redistribute the events to the other pages from the same domain via BroadcastChannel.

    • zakaria chahboun
      zakaria chahbounFeb 12, 2025

      Yes, But you can use one connection with multiple events.

  • Frozen Forest Reality Technologies
    Frozen Forest Reality TechnologiesFeb 12, 2025

    this requires http2, right ? SSE requires server-push which are available after http2

    • Troy High
      Troy HighFeb 12, 2025

      @ffreality , SSE works with regular http, however, there is a connection limitation as @dylan_westraadt_92f0c807d mentioned. If using http/2 then the connection limit can be negotiated.

    • zakaria chahboun
      zakaria chahbounFeb 12, 2025

      Actually, SSE doesn't require HTTP/2. It's designed to work over HTTP/1.1 as well. Unlike HTTP/2's server push, which allows the server to proactively push resources to the client, SSE uses a single open connection over HTTP to stream events to the client. The key here is that SSE works through a long-lived connection, but doesn't require the features of HTTP/2 like multiplexing or server push.

  • Octavio Santi
    Octavio SantiFeb 12, 2025

    I dont think this will replace the websockets, its just another technology for different use cases. SSE is for one way comunication and is more related to send notifications between the client and the server (for example in my job we have a react app who run inside of a 3rd party old electron app who has our app inside of an iframe and we needed to use SSE for sending an event to revoke all cookies in the electron application). If I need a chat or something "in real time" id still prefer to use web socket, things like push notifications SSE is the best choice

    • zakaria chahboun
      zakaria chahbounFeb 12, 2025

      Of course, it's not a replacement because they serve different purposes. But if you want to deal with real-time data, you should consider SSE first. If you need a more complex, duplex channel, then WebSockets are the way to go!

      • Bobby Bridgeman
        Bobby BridgemanFeb 13, 2025

        The title implies it is a replacement for ws, which it is not. In Blazor Server, SSE is a fallback to WS should they not be available. I.e It wouldn't be a fallback if it was a replacement.

  • Mohit Majumdar
    Mohit MajumdarFeb 12, 2025

    can we get same SSE for python based backends???

    • zakaria chahboun
      zakaria chahbounFeb 12, 2025

      Yes, Just an HTTP GET request with specific headers 😊

  • KUNDAN KUMAR
    KUNDAN KUMARFeb 12, 2025

    Hi
    I tried SSE in my project. It worked great but I was not able to configure nginx properly for this.
    If you have any suggestions please let me know.
    Thanks in advance.

    • zakaria chahboun
      zakaria chahbounFeb 12, 2025

      SSE requires keeping the connection open for a longer time, so you need to make sure NGINX is configured to handle that.

      Here are a few suggestions:

      1. Increase the buffer size and timeouts: SSE streams data continuously, so you need to adjust some NGINX settings. For instance, you might need to set a larger buffer and increase the timeout:
      location /events {
          proxy_pass http://your_backend_server;
          proxy_http_version 1.1;
          proxy_set_header Upgrade $http_upgrade;
          proxy_set_header Connection 'keep-alive';
          proxy_set_header Host $host;
          proxy_cache_bypass $http_upgrade;
          proxy_set_header X-Real-IP $remote_addr;
          proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
      
          # Adjust timeouts for long-running connections
          proxy_read_timeout 3600s;
          proxy_send_timeout 3600s;
      
          # Optional: Disable buffering for real-time data
          proxy_buffering off;
          client_max_body_size 0;
      }
      
      Enter fullscreen mode Exit fullscreen mode
      1. Keep the connection alive: Make sure the server and NGINX don’t timeout prematurely while the connection is open. The proxy_read_timeout and proxy_send_timeout parameters are key here.

      2. Turn off buffering: SSE requires that data be pushed to the client immediately, so turning off buffering in NGINX with proxy_buffering off is important for real-time delivery.

      Whatch this video:
      youtu.be/qoEq_Ro1wjU

  • Albi Rental Belitung
    Albi Rental BelitungFeb 12, 2025

    thanks

  • Rafa Mori
    Rafa MoriFeb 13, 2025

    Image description

  • Manpreet Singh
    Manpreet SinghFeb 13, 2025

    Informative!!

  • W (spotlight2001)
    W (spotlight2001)Feb 13, 2025

    If you have one app composed of 10 microfrontends ...
    I wonder if each microfrontend should make a separate SSE Http conn with its microservice per use case. In contrast to having a central micrsoservice and microfrontend for SSE.

  • iBerry Boi
    iBerry BoiFeb 13, 2025

    I use SSE in my twitch application to send updates to my widgets. Keep in mind that if you actually plan to deploy to production, you are going to have to do some configuration to get your SSE working but it's pretty easy with nginx.

  • Thuc Le
    Thuc LeFeb 19, 2025

    Hi, my question is, can we keep the long-live connection with HTTP? Do we need to implement a ping/pong mechanism to keep the connection from being dropped or disconnected during long time of no event sending?

    • zakaria chahboun
      zakaria chahbounFeb 19, 2025

      The connection will close on timeout, and the SSE will reconnect automatically

Add comment