Dev.to WebDev 🛠 Dev 👁 0 📖 3 min read

A Connected WebSocket Doesn’t Mean Your Crypto Prices Are Fresh

A crypto dashboard can look healthy while displaying an old price. The WebSocket is connected. The status indicator is green. The last quote still looks plausible. But connection status answers only one question: does

A crypto dashboard can look healthy while displaying an old price.

The WebSocket is connected. The status indicator is green. The last quote still looks plausible.

But connection status answers only one question: does the transport appear to be available? It does not establish that the application has received recent, valid data for the instrument on screen.

For developers building market dashboards, freshness deserves its own state.

Track three different signals

A useful design separates:

  • Connection state: Is the transport connected, reconnecting, or disconnected?
  • Feed activity: When did the application last receive a valid message?
  • Quote freshness: When was the displayed instrument last updated?

These signals can disagree.

A heartbeat can keep arriving while a subscription stops producing quotes. One instrument can update normally while another becomes stale. A message can arrive now but contain an old event timestamp.

A single green dot hides these differences.

Keep event time and receive time separate

An event timestamp describes when the source says something happened. A receive timestamp records when your application observed it.

Keep both when the feed provides them.

type QuoteObservation = {
  instrument: string;
  price: string;
  sourceEventTimeMs: number | null;
  receivedAtMs: number;
  receivedAtMonotonicMs: number;
};

This is an illustrative data model, not a provider-specific payload.

In a browser, Date.now() can provide a timestamp for display and logging. performance.now() can measure elapsed time within the current page session without depending on changes to the system clock.

Do not persist a performance.now() value and compare it across page reloads.

Also, label timestamps precisely. “Last received” and “market event time” communicate different information.

Define freshness around the feed’s behavior

A fixed timeout is easy to implement, but it needs context.

A trade feed may remain quiet because no trades occurred. A quote feed might publish only when values change. Another service might promise periodic snapshots.

Silence has a different meaning in each case.

Before selecting a threshold, check:

  • Whether messages are periodic or event-driven.
  • Whether heartbeats are separate from market updates.
  • Whether sequence numbers or subscription acknowledgements exist.
  • Whether the provider documents snapshot and reconnect behavior.

A five-second threshold can be an application policy. It should not be presented as a universal definition of stale market data.

When the feed does not provide enough information, show uncertainty rather than inventing confidence.

Make stale data visible without turning it into zero

When a quote becomes stale, replacing its value with 0 introduces a new error. Zero is a price, not a missing-data marker.

A clearer interface can retain the last known value while changing its presentation:

Last received price: 64,250.00

No quote update received for 18 seconds.

The number above is only an example.

Remove animations or indicators that imply a fresh update. Avoid calculating apparently current portfolio totals from old quotes without showing their age.

For applications that can submit orders, define separately which actions require fresh data and how the backend enforces that requirement. A browser warning alone is not an execution safeguard.

Treat reconnection as a recovery process

Reconnecting the socket does not necessarily repair the application’s local state.

Depending on the provider’s protocol, recovery may require resubscribing, fetching a new snapshot, buffering updates, or checking sequence continuity.

For an order book, missing one incremental update can leave a plausible-looking but incorrect book. Receiving another message does not prove that the gap has been repaired.

Keep the interface in a recovering state until the documented synchronization process completes.

Test the failures that still look normal

Useful tests include situations where the screen appears healthy:

  • Heartbeats continue, but quotes stop.
  • One instrument freezes while others update.
  • An older event arrives after a newer one.
  • The connection returns without subscription acknowledgement.
  • The browser tab resumes after being suspended.
  • An order-book sequence gap appears.

For each case, check both the internal state and the user-visible result.

A reliable dashboard should help users understand what it knows, when it learned it, and where its information may be incomplete.

“Connected” is useful information. Give “fresh” its own evidence.

This article was drafted with AI assistance.

📰 Read the original article on Dev.to WebDev

Originally published by Dev.to WebDev. Aggregated on AIWithGhost for educational purposes — full credit and traffic to the original publisher.