Why polling stops working
If you've built a live scoreboard before, you probably started with a setInterval hitting a REST endpoint every few seconds. That works fine for a handful of users checking a handful of matches. It stops working the moment you have real traffic, because every refresh is a new request, most of which return nothing new, and your rate limit burns down whether the score changed or not.
A push-based connection flips that around: the server tells you when something changes instead of you asking repeatedly. For live sports specifically, this matters a lot, since a goal or a point can happen at any second and users notice lag immediately.
Before you start
You'll need an API key for this, same as the REST endpoints. Orbistats' free tier covers WebSocket access too: https://orbistats.com/signup.html
Worth reading the WebSocket section of the docs before wiring this up, since message shapes and event names are the kind of detail you want confirmed rather than guessed: https://orbistats.com/developers/documentation.html
Opening the connection
The general shape of this kind of integration is a WebSocket connection you authenticate on open, then subscribe to specific matches or a whole sport feed. Something like:
const socket = new WebSocket("wss://api.orbistats.com/v1/stream?api_key=YOUR_API_KEY");
socket.addEventListener("open", () => {
socket.send(JSON.stringify({
action: "subscribe",
channel: "football",
match_id: "match_50231"
}));
});
socket.addEventListener("message", (event) => {
const update = JSON.parse(event.data);
console.log(update);
});
A note before you copy this: the connection URL, the subscribe message shape, and the field names above are written from the general convention for this kind of sports data stream, not a confirmed payload I've inspected directly. Some providers key subscriptions by sport, others by a single match id, others let you subscribe to both at once. Confirm the exact message format in the docs before you build around it: https://orbistats.com/developers/documentation.html
Handling reconnects
This is the part polling never made you think about. A WebSocket connection can drop for all kinds of reasons unrelated to your code, a laptop going to sleep, a flaky mobile network, a load balancer cycling connections. If you don't handle reconnects, your scoreboard just silently stops updating and nobody notices until someone complains.
A basic reconnect loop with backoff:
function connect() {
const socket = new WebSocket("wss://api.orbistats.com/v1/stream?api_key=YOUR_API_KEY");
let retryDelay = 1000;
socket.addEventListener("open", () => {
retryDelay = 1000; // reset backoff once we're actually connected
});
socket.addEventListener("close", () => {
setTimeout(connect, retryDelay);
retryDelay = Math.min(retryDelay * 2, 30000);
});
return socket;
}
Whether the server also sends you a snapshot on reconnect, or expects you to re-subscribe from scratch, is exactly the kind of detail that varies between providers and is worth confirming rather than assuming.
Falling back to REST
Not every environment plays nicely with long-lived WebSocket connections, some corporate networks and proxies block them outright. Having a REST fallback that polls at a slower interval when the socket fails to connect a few times in a row is a reasonable safety net rather than leaving users with a scoreboard that just never loads.
When polling is still fine
None of this means polling is wrong by default. If you're showing scores that update every few minutes rather than every few seconds, or you're building something low-traffic and the added complexity of connection state, reconnects, and subscription management isn't worth it yet, a simple interval-based fetch against the REST API is still the pragmatic choice. Full REST reference here: https://orbistats.com/developers/api-reference.html
Where to go from here
This covers the raw WebSocket path. If you'd rather skip building the UI around it entirely, there's also a drop-in live score widget that handles the connection and rendering for you: https://orbistats.com/widgets.html
Curious how others here are handling reconnect logic in production, exponential backoff, a fixed retry count, something else?

Top comments (0)