Why ChatGPT Uses Server-Sent Events (SSE) and How to Implement SSE in Spring Boot

This article explains why ChatGPT adopts Server-Sent Events for streaming responses, compares SSE with WebSocket, outlines SSE's core principles and best‑practice considerations, and provides a complete Spring Boot example—including server‑side Java code and client‑side HTML—to demonstrate real‑time data push.

ITPUB
ITPUB
ITPUB
Why ChatGPT Uses Server-Sent Events (SSE) and How to Implement SSE in Spring Boot

Why ChatGPT Uses SSE

When exploring ChatGPT’s usage, we discovered that it returns data using a streaming approach. Although a persistent full‑duplex connection could be used, ChatGPT opts for Server‑Sent Events (SSE), which fits the scenario where large language model responses may take a long time and need incremental delivery to keep the user’s page open.

What Is SSE?

SSE (Server‑Sent Events) is a web technology that allows a server to push data to a client over a single, long‑lived HTTP connection. It is defined in the HTML5 specification and uses the EventSource API on the browser side. Data is sent as plain text (often JSON) with the MIME type text/event-stream.

Simple to use – text‑based format.

Unidirectional – server‑to‑client only.

Real‑time – the server can push updates without the client polling.

SSE vs. WebSocket

Direction: SSE is one‑way (server → client); WebSocket supports full duplex.

Connection establishment: SSE uses a regular HTTP GET request; WebSocket upgrades the connection with a custom protocol.

Compatibility: SSE works on any modern browser without extra handshakes; WebSocket is widely supported but may encounter restrictions in some network environments.

Use cases: SSE suits scenarios like live stock quotes or news feeds; WebSocket is better for chat, collaborative editing, or any bidirectional interaction.

How SSE Works

Client sends an HTTP GET request to the SSE endpoint.

Server responds with status 200 and Content‑Type: text/event-stream.

Server pushes events, each consisting of lines such as data:, id:, or event:, separated by a double newline.

Browser receives events via the EventSource object and triggers JavaScript handlers.

If the connection drops, the client automatically reconnects, optionally sending the last received event ID via the Last‑Event‑ID header.

Practical Considerations When Using SSE

Asynchronous handling: Use async processing (e.g., Spring’s @Async or CompletableFuture) to avoid blocking server threads.

Timeout management: Set appropriate timeouts on SseEmitter and handle onTimeout to free resources.

Error handling: Use SseEmitter.completeWithError() on the server and eventSource.onerror on the client.

Memory management: Release SseEmitter instances promptly after disconnection to prevent leaks.

Concurrency: For many simultaneous connections, employ thread pools or reactive approaches to keep resource usage low.

Client compatibility: Verify that target browsers support SSE; provide a fallback (e.g., long polling) for older browsers.

Spring Boot SSE Example

Below is a minimal Spring Boot controller that streams random stock prices to the client.

import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.servlet.mvc.method.annotation.SseEmitter;
import java.util.Random;

@RestController
public class StockController {
    @GetMapping(value = "/stock-price", produces = MediaType.TEXT_EVENT_STREAM_VALUE)
    public SseEmitter streamStockPrice() {
        SseEmitter emitter = new SseEmitter();
        Random random = new Random();
        new Thread(() -> {
            try {
                while (true) {
                    double price = 100 + random.nextDouble() * 10;
                    String message = String.format("%.2f", price);
                    emitter.send(SseEmitter.event().data(message));
                    Thread.sleep(1000);
                }
            } catch (Exception e) {
                emitter.completeWithError(e);
            }
        }).start();
        return emitter;
    }
}

The controller maps /stock-price to a method that returns an SseEmitter. A background thread generates a random price every second and pushes it to the client.

Client‑Side HTML

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8">
    <title>Real‑Time Stock Price</title>
  </head>
  <body>
    <h1>Real‑Time Stock Price</h1>
    <div id="stock-price"></div>
    <script>
      const eventSource = new EventSource('/stock-price');
      eventSource.onmessage = function(event) {
        document.getElementById('stock-price').innerHTML = event.data;
      };
    </script>
  </body>
</html>

The browser creates an EventSource pointing to /stock-price. Each incoming message updates the displayed price, demonstrating a complete end‑to‑end SSE solution.

Key Takeaways

SSE is a lightweight, HTTP‑based push technology that excels in scenarios requiring server‑to‑client streaming, such as live dashboards or notifications. It offers automatic reconnection and simple text‑based messages but cannot handle bidirectional communication, has connection‑count limits, and only supports GET requests. For truly interactive or high‑throughput use cases, WebSocket may be more appropriate, while SSE remains an excellent choice for lightweight, one‑way updates.

Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

JavaSpring BootWebSocketreal-time communicationServer-Sent EventsSSE
ITPUB
Written by

ITPUB

Official ITPUB account sharing technical insights, community news, and exciting events.

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.