Why ChatGPT Chooses SSE and How to Build Real‑Time Apps with Spring Boot
This article explains the Server‑Sent Events (SSE) technology behind ChatGPT's streaming responses, compares SSE with WebSocket, outlines its core implementation steps, and provides a complete Spring Boot example for pushing live stock prices to browsers.
When exploring ChatGPT's usage, we discover that it streams results using Server‑Sent Events (SSE) instead of a full‑duplex protocol. SSE fits the model where a large language model needs to push incremental data to the user during long‑running computations, preventing the user from abandoning the page.
What Is SSE?
SSE (Server‑Sent Events) is a web technology that lets a server push data to a client over a persistent HTTP connection. It uses the EventSource API in browsers and sends data with the text/event-stream MIME type. Compared with polling, SSE offers lower latency and simpler, text‑based messages (plain text or JSON).
Simple to use: plain‑text format.
Unidirectional: server → client only.
Real‑time: the server can push data as soon as it is available.
SSE vs. WebSocket
Direction: SSE is one‑way (server to 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 in most modern browsers without extra handshakes; WebSocket may face restrictions in some network environments.
Use cases: SSE suits scenarios like live stock quotes, news feeds, or logs; WebSocket is better for chat, collaborative editing, or any bidirectional interaction.
Choosing between them depends on whether you need only server‑to‑client pushes (SSE) or full two‑way communication (WebSocket).
How SSE Works
Connection setup: The client sends an HTTP GET request to a specific endpoint.
Server response: The server replies with status 200 and Content‑Type: text/event-stream.
Data push: The server streams events, each consisting of lines like data:, id:, or event:, separated by a double newline.
Client handling: The browser fires JavaScript events (e.g., onmessage) for each received event.
Reconnection: If the connection drops, the client automatically retries, optionally sending Last‑Event‑ID so the server can resume from the last event.
Practical Considerations When Using SSE
Process requests asynchronously (e.g., using @Async or CompletableFuture) to avoid blocking server threads.
Set a timeout on the SseEmitter and handle onTimeout to free resources.
Handle errors with completeWithError and client‑side eventSource.onerror.
Release the SseEmitter when a client disconnects to prevent memory leaks.
Use thread pools or other async mechanisms for high‑concurrency scenarios.
Check browser compatibility; 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 connected browsers.
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 endpoint returns an SseEmitter that continuously emits a JSON‑compatible string representing the latest price. The @GetMapping annotation maps /stock-price to this method and sets the response type to text/event-stream.
On the client side, a simple HTML page creates an EventSource pointing to /stock-price and updates the DOM whenever a new message arrives.
<!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 establishes an SSE connection to /stock-price, receives price updates every second, and displays them instantly.
Conclusion
SSE provides a lightweight, HTTP‑based way to push real‑time data from server to client, with built‑in reconnection and simple text framing. It excels for unidirectional streams such as live feeds, logs, or notifications. However, for bidirectional communication, high‑throughput or low‑latency needs, WebSocket remains the better choice.
Senior Brother's Insights
A public account focused on workplace, career growth, team management, and self-improvement. The author is the writer of books including 'SpringBoot Technology Insider' and 'Drools 8 Rule Engine: Core Technology and Practice'.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
