DEV Community

Cover image for WebSockets Can Stall Without Disconnecting — And It’s Worse on Android
Jit Chakraborty
Jit Chakraborty

Posted on

WebSockets Can Stall Without Disconnecting — And It’s Worse on Android

While building a real-time messaging system, I ran into something frustrating:

The WebSocket shows “connected”… but nothing works.
No errors.
No disconnect event.
No messages going through.
Just a connection that looks alive — but is effectively dead.

The Problem

On Android (especially Chrome and background scenarios), WebSockets can silently stall when:

Network switches (WiFi → Mobile)
App goes into background
Device enters power-saving mode

The connection stays OPEN, but:

messages don’t send
no events are received
no onclose or onerror fires

From the UI → everything looks fine
From reality → it’s broken

What “Connected” Actually Means

WebSockets only tell you:

“The connection is open”
They don’t guarantee:
“The connection is still usable”

Here’s a typical example — the socket is technically connected:

But this state alone doesn’t tell you if data is actually flowing.

What Doesn’t Fix It

A common approach is:

“If the same user reconnects, replace the old socket”
That helps with duplicate connections, but not this issue.
Because here:

the user never reconnects
the connection just stalls silently
What Actually Works

  1. Heartbeat (Ping/Pong)

Instead of trusting the connection, verify it.

setInterval(() => {
socket.send(JSON.stringify({ type: "ping" }))
}, 5000)

The server responds with a pong.
If that stops → the connection is dead.

  1. Track Activity

Keep track of the last message received:


if (Date.now() - lastMessageTime > TIMEOUT) {
socket.close()
reconnect()
}

If no activity → force reconnect.

  1. Don’t Wait for onclose If you rely on:

onclose
onerror
You’ll miss silent failures.
Why This Matters

The worst part about this issue:

It doesn’t break loudly — it fails silently.
Which means:

users think they’re connected
messages don’t arrive
debugging becomes painful

Curious if others have hit this — especially on Android — and how you handled it.

Top comments (0)