Build1 distinct publisher3 min readUpdated
A dev.to write-up argues the failure that hurts production clients is the socket still reporting OPEN with no data arriving. Reconnect code never runs if nothing declares the connection dead.
The Engineer · Build desk
Compiled by The EngineerSomething wrong?How this is made
A dev.to post on WebSocket reconnection makes a point worth taking seriously: the failure you can handle is the one that throws, and the failure that hurts you is the one that goes quiet, with the TCP connection technically open, the socket object still reporting `readyState === OPEN`, and no data arriving [1]. That inverts where most client effort goes, because the backoff-and-replay machinery everyone writes is downstream of a decision nobody makes: declaring the connection dead.
The author's example is a perpetual futures grid trading bot that consumes a live exchange market feed over WebSocket and places orders from it [2]. A feed that stops updating without the client noticing means the bot is reacting to a price snapshot that went stale minutes ago, while every downstream risk check assumes the data is current [3]. The same failure surface applies to order-status streams, chat, collaborative editing, IoT telemetry, and live dashboards [4].
The post names the core mistake plainly: trusting `readyState`, which reports what the local socket object believes rather than whether packets are moving [6]. A NAT table entry that expired, or a phone switching from Wi-Fi to cellular, leaves the socket in `OPEN` with nothing coming through [6]. `onclose` does not always fire, and a silently half-open socket can sit there for minutes [c5a].
The proposed fix is an application-level heartbeat: send a ping on an interval, expect a pong within a deadline, and if the pong does not arrive, tear the connection down yourself rather than waiting on a TCP timeout that may be minutes away [7]. The sample implementation is deliberately small. A `setInterval` sends the ping and arms a `setTimeout` death deadline; any inbound pong clears that timer; if it expires, an `onDead` callback fires and the socket's own claim to be OPEN is ignored [12].
The sizing argument is the part to copy. RFC 6455 defines native ping/pong frames and the Node.js `ws` library exposes them, but browsers give no access to control frames, so browser clients send an application-level heartbeat message instead [8]. Either way, the timeout must be shorter than any upstream idle limit you know about; load balancers commonly cut idle connections at 60 seconds, and the post suggests a 20-second interval with a 10-second timeout [9]. That puts worst-case detection at roughly 30 seconds, half the idle limit it is meant to beat [11].
The second detail is the one that explains why teams get away with bad heartbeats for a long time. Any inbound traffic is proof of life, so on a firehose delivering market data every few milliseconds a missed pong is nearly impossible [10]. The heartbeat earns its keep during quiet periods, when a feed with nothing to say is indistinguishable from a feed that has died [10].
What to check in your own client: whether anything at all measures time since last inbound message, and whether that threshold is set below your load balancer's idle cut [9]. Then the three problems that follow detection, which the post lists and most demos skip: reconnecting without a thundering herd, since ten thousand clients returning at once will knock the server over again [c5b]; restoring subscriptions, because a fresh socket has none and the server has forgotten who you are [c5c]; and the gap, because messages published during the outage are gone unless you do something about it [c5d].
Follow any of these and your For You feed starts watching them — no settings page required.
Ranked by verification strength, evidence, and original report placement.
A WebSocket that throws an error is easy to handle; the dangerous case is the connection that goes quiet, where the TCP connection is technically still open, the socket object still reports readyState === OPEN, and no data is arriving, so the application believes it has a live feed.
Detecting a dead connection is one of four things that go wrong in production: onclose does not always fire, and a silently half-open socket can sit there for minutes.
The core mistake is trusting readyState, which tells you what the local socket object believes rather than whether packets are actually moving; a connection dropped at the network layer, such as an expired NAT table entry or a phone switching from Wi-Fi to cellular, can leave the socket in OPEN with nothing coming through.
The author encountered this failure while building a perpetual futures grid trading system whose bot consumes a live exchange market feed over WebSocket and makes order decisions from it.
A dropped feed the client does not notice means the bot is reacting to a price snapshot that stopped updating minutes ago, while every layer of downstream risk management assumes the feed is current.
The same failure surface applies to any product built on a live feed, including market data, order-status streams, chat, collaborative editing, IoT telemetry, and live dashboards.
Evidence-backed comparisons of source perspectives and observed adoption signals. Read the methodology
Which Builder, Operator, and Investor concerns the observed source mix emphasized—not a truth score.
Evidence, demonstrated adoption, hype gap, incentives, and confidence are assessed independently, each on its own current evidence. How these are measured.
Mechanism-level reasoning with standards anchor, no measurements
The failure mechanism is checkable rather than speculative: readyState reports local socket belief, RFC 6455 defines ping/pong control frames, and the browser WebSocket API does not expose them, all of which the article states and a reader can verify. A working TypeScript reference implementation is published. What is absent is any measurement — no logged incidents, no detection-latency data, no before/after comparison from the author's own bot — and the timing recommendations rest on an unsourced generalization about 60-second load-balancer idle cuts. Single publisher, so nothing is independently corroborated.
One self-reported deployment, no measurable uptake
The only usage signal is the author's own perpetual futures grid trading bot, disclosed without scale, duration, connection counts, or incident data. No third-party deployments, downloads, library releases, or benchmark results are supplied, so adoption of the described pattern cannot be scored from this material.
Framing slightly ahead of the demonstrated case
The substance is modest and proportionate — heartbeats, backoff with jitter, replay — and the article openly limits itself by noting inbound traffic already proves liveness in a data firehose. The overstatement is mild and mostly in framing: the headline verdict that liveness detection 'beats' reconnect logic is presented as a general production truth while the supporting evidence is one unmeasured personal trading bot, and the specific 20s/10s tuning is offered as guidance without any latency or false-positive data behind it.
Practitioner credibility post, no product being sold
This is an individually authored dev.to post with no vendor, no funding disclosure, no paid product, and no pricing or licensing angle. The visible incentive is ordinary developer-reputation building, reinforced by foregrounding the author's own trading system as the origin story, which is a mild reason to present the pattern as more decisive than measured. Nothing in the supplied material indicates commercial sponsorship.
Uncontested single-source guidance on a well-understood mechanism
Confidence is moderate: the underlying mechanism is verifiable against the WebSocket specification and platform APIs, the reasoning is internally consistent, and nothing in the cluster contradicts it. It is held back by a single publisher, zero measurements, an unsourced load-balancer premise, adoption that cannot be scored, and a source body truncated before the replay and state-restoration sections it promises.
build
A GAN beauty filter is a device budget allocation, not a feature toggle1 distinct publisher
build
The 2-4 seconds you pay per file: batch tsc once per agent session, not once per edit1 distinct publisher
build
The Dutch VAT checksum stopped working in 2020 and your billing pipeline may not know1 distinct publisher
build
Write the ledger row before the transcription call, or stop guessing at per-tenant margin1 distinct publisher
Distinct publishers with included, body-backed reporting in this cluster.
dev.to
1 article · August 21, 2026