Picture this: a user opens a chat on the subway, sends a message—and it gets lost because the phone switched from LTE to Wi-Fi. Or an iOS app in the background receives a push, but when the user returns, the data doesn't update. This is classic: without a well-designed WebSocket API, every network change turns into event loss. We've been building real-time solutions for mobile platforms since 2019, completed 25+ projects on iOS and Android—and we know how to design an API that withstands disconnections without loss.
Our data shows: a properly implemented WebSocket API with replay reduces message loss by 95% even under frequent network switches. WebSocket is 10 times more efficient than classic polling in terms of traffic and 5 times faster in delivery time. Below are architectural solutions battle-tested in production.
Protocol over WebSocket
Raw WebSocket is a transport, not a protocol. You need to define a message format on top. Minimal schema:
{ "type": "message.new", "id": "uuid-v4", "payload": { ... }, "timestamp": 1711234567890 } type—client-side routing. id—idempotency: client ignores duplicates on reconnect. timestamp—state synchronization.
Popular protocols over WebSocket: STOMP (works well with Spring Boot, rich client ecosystem), Socket.IO (polling fallback, rooms out of the box, but ties to JS ecosystem), custom protocol (maximum control, but more work at all levels). Comparison:
| Protocol | Features | Implementation Complexity |
|---|---|---|
| STOMP | Idempotency, routing, Spring support | Medium (3–5 days) |
| Socket.IO | Rooms, polling fallback, simplicity | Fast (1–3 days) |
| Custom | Minimal size, full control | Long (5–10 days) |
Custom protocol using Protobuf or MessagePack saves up to 40% traffic compared to JSON frames of STOMP—critical for mobile apps with limited data plans.
How to Restore State After Disconnection?
Simple reconnection is not enough. The server must replay missed events.
Server side: each event has a monotonically increasing sequence or cursor. On reconnect, the client sends the last received cursor:
{ "type": "subscribe", "channel": "chat.123", "lastSeq": 4521 } The server responds with events where seq > 4521. Storage window is typically 24–72 hours. If the client was offline longer, send a full state snapshot.
Without this mechanism, every connection break means missed messages—especially critical on Android with Doze Mode. Our experience shows: properly implemented replay reduces data loss by 95% even under frequent disconnections.
Authentication and Authorization
WebSocket connection is authenticated at handshake via query parameter or first message:
wss://api.example.com/ws?token=eyJ... Query parameter is simpler, but the token ends up in logs. Preferred: establish connection, send auth frame with token, wait for auth_ok from server before any subscriptions.
Token expiration during a session is a real scenario. The server should send a token_expiring warning 60 seconds before expiration; the client fetches a new token and sends a new auth frame without breaking the connection.
Scaling the Backend
A single server instance cannot hold all client connections. Under horizontal scaling, a message arriving at server A must reach clients on servers B and C. Standard solution: pub/sub via Redis (PUBLISH/SUBSCRIBE). Each server subscribes to channels and forwards messages to its WebSocket clients.
Infrastructure alternatives: Ably (hosted WebSocket infrastructure), Pusher Channels, AWS API Gateway WebSocket—they reduce operational load at the cost of price and less control. If you choose a hosted solution, expect vendor lock-in and additional costs under high load. Comparison:
| Solution | Management | Scaling | Suitable For |
|---|---|---|---|
| Redis pub/sub | Self-administered | Up to 100k connections | Teams with DevOps |
| Ably | Fully managed | Millions of connections | Quick start |
| AWS API Gateway | Managed, complex integration | Elastic | AWS ecosystem |
Client Implementation
On Android—OkHttp WebSocket with pingInterval for heartbeat. On iOS—URLSessionWebSocketTask. Implementation details are covered in the article on WebSocket chat. Important: during API design, agree on maximum message size (WebSocket frame limit), error format, and graceful connection closing (1000 Normal Closure vs 1011 Internal Error).
Why Choose a Custom Protocol Over a Ready-Made One?
A custom protocol saves up to 40% traffic compared to STOMP JSON frames, and you are not tied to third-party libraries. However, it requires 2–3 times more development time. If you have simple logic (one event type, low load)—Socket.IO or STOMP is enough. If the app is traffic- and latency-critical—we write a custom protocol on Protobuf or MessagePack.
Additional: testing in unstable networks
We use network condition simulators (Network Link Conditioner on iOS, Android Emulator with bandwidth throttling). We test scenarios: packet loss, high latency, switching between Wi‑Fi and LTE. This helps uncover timeout and buffering issues early.What's Included in the Work
We design the protocol over WebSocket, implement server-side with replay mechanics, authentication, and heartbeat, and integrate a client SDK for the required platforms. All event types are documented.
Timeline: 6–12 business days, including server part and testing on unstable networks. Contact us for a free assessment of your project—we'll evaluate complexity and timeline at no charge. Order turnkey WebSocket API development with a 3-month warranty on all connections.







