Mobile Messenger Development
Sending a message is not enough. Users expect it to arrive instantly, not get lost during network drops, and stay confidential. When building a messenger, common problems arise: message loss on unstable networks, data leaks over unencrypted channels, high battery consumption. We build messengers that solve these at the protocol level: WebSocket for real-time, E2EE on Signal Protocol, push-wake for battery savings. We'll assess your project within 2 business days.
How to Ensure Guaranteed Message Delivery?
WebSocket is the basic transport for real-time exchange. On mobile devices it doesn't persist forever: iOS kills background connections after 30 seconds of inactivity, Android Doze Mode closes them on idle. The right solution — WebSocket in foreground + push notifications (FCM/APNs) for wake-up. On receiving a push, the client reconnects and downloads new messages. This approach is 5 times more efficient than constant polling in terms of traffic.
Step-by-step delivery implementation
- Client generates a UUID and per-conversation sequence number, saves the message in local DB with status
sending. - Sends the message over WebSocket with a callback for acknowledgment (
ack). - Server confirms receipt — client changes status to
sent. - On receiving push notification from server, client updates status to
delivered. - If user reads — status
read.
A queue of unsent messages with automatic retry on connection restore.
// iOS — message delivery status management enum MessageStatus: String, Codable { case sending, sent, delivered, read, failed } class MessageStore { func sendMessage(_ text: String, to conversationId: String) { let msg = Message( id: UUID().uuidString, conversationId: conversationId, body: text, status: .sending, timestamp: Date() ) coreDataContext.insert(msg) webSocketClient.send(msg) { [weak self] result in switch result { case .success: self?.updateStatus(msg.id, .sent) case .failure: self?.updateStatus(msg.id, .failed) } } } } Delivery approach comparison:
| Method | Latency | Battery drain | Reliability |
|---|---|---|---|
| Polling (every 5s) | 5s | High | Medium |
| WebSocket | <1s | Medium | High (with reconnect) |
| WebSocket + Push | <1s | Low | Very high |
Why E2EE is a Basic Necessity?
E2EE is not an option, but a standard for a serious messenger. The industry standard — Signal Protocol includes Double Ratchet and X3DH. Implementation via official libsignal libraries (ports for iOS and Android). On registration, keys are generated (identity key, signed prekey, one-time prekeys), public parts are uploaded to the server. At conversation start, the client downloads the recipient's prekey, performs X3DH, and establishes an encrypted session. The server never sees plaintext.
Details of Signal Protocol Implementation
- Double Ratchet: each new session generates session keys, old ones are destroyed (perfect forward secrecy). - X3DH: three Diffie-Hellman between identity/public/prekey to establish a shared key. - The server side never has access to user private keys.Encrypted backup of conversation history is stored with a key known only to the user (PIN/passphrase).
History Storage and Synchronization
SQLite via Room (Android) or CoreData/GRDB (iOS). DB schema: conversations, messages, attachments, reactions. Indexes on conversation_id + timestamp for fast feed loading. Full-text search — FTS5.
Pagination — reverse cursor: load the last N messages, on scroll up request next. Storing full history locally is impractical: limit to last N messages per conversation, rest lazy load from server. This saves up to 40% of traffic and local DB size.
Media and Battery Optimization
Photos, videos, documents — separate upload pipeline: presigned URL → upload to object storage → link in message. Thumbnail generated client-side and attached as base64 blurred preview (blurhash) — shows placeholder before original download.
Voice messages: recording via AVAudioRecorder (iOS, opus through AVAudioSession) or MediaRecorder (Android). Codec Opus 24 kbps. Waveform preview — sample amplitudes normalized to size.
Image compression before sending: UIGraphicsImageRenderer with max size 1280px and JPEG quality 0.8 — without this, each photo from a modern smartphone weighs 12+ MB. Reduces traffic by 10 times.
WebSocket keepalive — ping/pong every 25 seconds. APNs Priority 5 (low priority) for background notifications — doesn't wake screen; Priority 10 (high) — only for explicit incoming messages. This reduces battery consumption by 30%.
What Stages Does Mobile Messenger Development Include?
- Documentation: architecture, protocol, API design, ER diagrams.
- Source code: repository with code review and CI/CD.
- Builds: beta TestFlight/Google Play Console, CI builds for staging.
- Access: store accounts, push certificates, provisioning profiles.
- Training: workshop for the client's team on modification and support.
- Support: 3 months post-release bug fixing.
Group Chats and Channels
Group chat up to 1000 participants — standard fan-out. Broadcast channels with tens of thousands of subscribers — asynchronous delivery via queue (Kafka). For E2EE in groups we use Sender Keys (Signal/WhatsApp): one encrypted stream for all participants, not N individual sessions. Mentions (@username) in group — push only to the mentioned user or with configurable notifications.
Group approach comparison:
| Approach | Participants | E2EE | Delivery latency |
|---|---|---|---|
| Fan-out (peer-to-peer) | ≤1000 | Yes | Low |
| Fan-out (main) | ≤1000 | Yes | Low |
| Broadcast (Kafka) | >10 000 | No | Medium |
| Sender Keys | ≤1000 | Yes | Low (single stream) |
Timelines and Cost
MVP with chat, media, and push without E2EE — 6–8 weeks. Full messenger with E2EE, voice messages, groups, and backup — 3–5 months. Cost is calculated individually after requirements audit. Contact us for a detailed discussion of your project. Order development right now — we guarantee transparency at every stage.







