KHD
KHD Labs Mobile & Web Studio

WebSockets vs Server-Sent Events for Mobile: A Real Battery & Reconnect Teardown

Why keeping a bidirectional WebSocket open drains phone batteries through cellular radio tail states, and why Server-Sent Events over HTTP/2 are superior for 90% of mobile feeds.

Tarek M.
•
Web Performance Director
• 7 min read
Studio Benchmark
Battery drain reduced by 34% over 8hr active shift
Problem Addressed: "App burns customer battery and gets flagged in iOS Battery Settings"

A ride-hailing and courier company in London noticed a disturbing trend in their driver exit surveys: “Your app eats 50% of my phone battery in four hours, even when plugged into my 12V car charger.”

When an app causes a phone to get physically hot to the touch in a windshield phone mount, you have a hardware-level problem.

The culprit wasn’t their GPS tracking loop. It was their WebSocket implementation.

The Cellular Baseband Radio State Machine

To understand why WebSockets kill mobile batteries, you have to look past the software layer and understand how cellular modems work in iOS and Android hardware.

A phone’s 4G/5G radio does not transmit continuously. It operates as a state machine managed by the cellular carrier’s radio network controller:

[RADIO ACTIVE / DCH]  ◄── Full power (High battery draw)
       │
       │ (10 - 15 seconds of inactivity: Tail State)
       ▼
[RADIO LOW POWER / FACH] ◄── Half power
       │
       │ (Another 5 - 10 seconds of silence)
       ▼
[RADIO IDLE / PCH]    ◄── Microamps (Battery preserved)

Every single time your WebSocket sends or receives an empty 2-byte ping/pong heartbeat frame to keep the TCP connection alive through NAT gateways, it wakes the cellular radio up to full high-power state.

The data transmission takes 20 milliseconds, but the cellular modem is forced to stay awake in its high-power “tail state” for the next 15 seconds waiting for subsequent traffic.

If your WebSocket client pings every 20 seconds, the cellular radio never sleeps. It runs at full power draw 100% of the time, burning milliampere-hours and generating noticeable heat.

The Case for Server-Sent Events (SSE) over HTTP/2

Unless you are building a real-time multiplayer FPS game or collaborative Figma canvas on a phone, mobile data flow is almost entirely unidirectional: the server has updates (ride dispatch, live order progress, message notifications), and the client is simply listening.

When you use Server-Sent Events (SSE) over an existing HTTP/2 or HTTP/3 connection:

  1. Multiplexing: The event stream shares the exact same TCP/QUIC connection already used for normal REST or GraphQL requests. No separate TLS handshake or socket allocation.
  2. Native Reconnect Handling: The browser and native HTTP clients (NSURLSession and OkHttp) automatically negotiate Last-Event-ID upon signal loss. The server replays missed events automatically:
    GET /api/v1/live-dispatch HTTP/2
    Host: api.khdlabs.internal
    Accept: text/event-stream
    Last-Event-ID: evt_01HV998Z8...
  3. Radio-Friendly Coalescing: Modern mobile operating systems can coalesce HTTP/2 stream reads, waking the CPU in bursts rather than holding an open raw TCP socket with unaligned keep-alives.

When Do You Actually Need WebSockets?

Only use a WebSocket on mobile if:

  • You require bidirectional message rates higher than 10 messages per second (e.g. real-time audio streams, live drawing cursors).
  • You cannot use HTTP/2 or HTTP/3 proxies in your client environment.

For everything else—live order trackers, notifications, market tickers, chat feeds—ditch the raw WebSocket. Use SSE with batched server flushes. Your users’ batteries will thank you.

Engineering Consultation

Encountering this bottleneck in your application?

We profile production repositories directly with native tooling (Xcode Instruments, Android Studio Profiler) to pinpoint the exact root causes.