A modern messaging platform allows people to exchange messages almost instantly, regardless of where they are or whether they are currently online. Behind that simple experience is a distributed system responsible for persistent connections, message ordering, offline delivery, group conversations, media storage, notifications, and encryption.
Designing a messaging application is a common system design interview problem because it combines very high traffic with demanding reliability requirements. Messages should not be silently lost, recipients should not see them in the wrong order, and reconnecting devices must be able to recover anything they missed.
In this post, we’ll design a messaging application similar to WhatsApp. The design is conceptual rather than a description of WhatsApp’s internal architecture.
A system design interview may begin with a broad prompt:
Design a messaging application like WhatsApp.
Before proposing an architecture, we need to establish what “like WhatsApp” means for this interview. A complete messaging platform could include voice calls, video calls, stories, public channels, payments, business accounts, disappearing messages, and many other features.
For this design, we will concentrate on the core messaging experience. Users can exchange one-to-one and group messages, send media, receive delivery and read receipts, use multiple devices, and recover messages after being offline.
The platform should deliver online messages with very low latency. It must also store undelivered messages reliably and protect conversation content with end-to-end encryption.
The most important parts of the design are persistent connections, message durability, delivery semantics, per-conversation ordering, and multi-device synchronisation.
The primary requirement is that a user can send a message to another user or group. The message may contain text or a reference to an encrypted media attachment.
Messages should move through several visible states. A message may initially be accepted by the server, later delivered to a recipient device, and eventually marked as read.
Users should be able to open a conversation and retrieve its recent history. If a device disconnects, it should receive any missed messages when it reconnects. A user with several devices should have a reasonably consistent conversation history across all of them.
Group conversations require membership management. Authorised users can create groups, add or remove participants, and send messages to all current members.
Presence indicators and typing notifications may also be supported, but they do not require the same durability as messages. If a typing event is lost, the system does not need to recover it later.
Voice calls, video calls, public broadcasts, stories, and payments will remain outside the initial scope.
The platform’s non-functional requirements are especially important. It should provide low delivery latency, high availability, durable storage, and horizontal scalability. Message ordering should be guaranteed within a conversation, but there is no need to provide one global order across every conversation in the system.
The first workflow is establishing a connection. After authentication, a client opens a persistent connection to a nearby messaging server. This connection allows the server to deliver messages without waiting for the device to poll repeatedly.
The second workflow is sending a message. The sender submits a message through its existing connection. The platform validates the sender’s membership, stores the message durably, and acknowledges it. The message is then routed to the recipient’s connected devices.
If the recipient is offline, the message remains available for later delivery. A push notification can alert the recipient without containing sensitive message content.
The third workflow is acknowledging delivery. A recipient device confirms that it received the message, and the resulting delivery status is synchronised back to the sender.
Reading a message creates another event. Depending on the user’s privacy settings, the platform can update the message’s read state and notify the sender.
Group delivery follows the same general process, but the accepted message must be distributed to many users and potentially several devices belonging to each user.
Suppose the platform has 500 million daily active users and each user sends an average of 50 messages per day.
This produces 25 billion messages per day, or approximately 290,000 messages per second on average. Traffic will not be evenly distributed, so peak throughput could reach several million messages per second.
If an average stored text message requires approximately one kilobyte after metadata and indexing are included, the system creates around 25 terabytes of message data each day before replication.
Media creates a much larger storage and bandwidth requirement. Images, videos, documents, and voice notes should therefore be stored separately from the message database.
Persistent connections also affect capacity. A messaging gateway may need to maintain hundreds of thousands of open connections. Supporting hundreds of millions of online devices requires a large, horizontally scaled connection layer.
The system should scale based on both message throughput and concurrent connections. These are related but separate workloads.
Messaging clients use a combination of persistent connections and conventional APIs.
Operations that require real-time communication, such as sending messages, receiving messages, and publishing delivery receipts, travel through a persistent protocol. REST-style APIs can be used for account management, conversation history, group administration, and media uploads.
A simplified public API might include:
POST /conversations
GET /conversations
GET /conversations/{conversationId}/messages
POST /conversations/{conversationId}/messages
POST /messages/{messageId}/delivered
POST /messages/{messageId}/read
POST /media/uploads
POST /groups/{groupId}/members
DELETE /groups/{groupId}/members/{userId}
A message contains a globally unique identifier, conversation identifier, sender, creation time, conversation sequence number, encrypted content, and content type.
The client should create a unique message identifier before sending. If the connection fails and the client retries, the server can recognise the identifier and return the existing result instead of storing the message twice.
A simplified encrypted message could look like this:
{
"messageId": "msg_192857203",
"conversationId": "conversation_7843",
"senderDeviceId": "device_42",
"sequence": 185,
"contentType": "text",
"ciphertext": "encrypted-content",
"sentAt": "2026-08-24T10:15:30Z"
}
The primary data entities include users, devices, conversations, conversation members, messages, delivery receipts, read receipts, and media references.
Messages are mostly immutable. Corrections, reactions, deletions, and status changes can be represented as additional events associated with the original message.
The system separates connection handling from durable message processing:
Web Client ──────┐
Mobile Clients ──┼──→ Global Traffic Router
Desktop Client ──┘ │
┌─────────┴─────────┐
↓ ↓
API Gateway Connection Gateways
│ │
└─────────┬─────────┘
↓
Message Service
│
┌────────────┼────────────┐
↓ ↓ ↓
Message Store Event Broker Conversation
Service
│
┌───────────┼───────────┐
↓ ↓ ↓
Delivery Presence Notification
Workers Service Service
│
↓
Connected Devices
Media → Object Storage → CDN
Users can access the platform through mobile, web, and desktop applications. Each registered device has its own identity and encryption keys.
Mobile devices may frequently disconnect or change networks. The client must reconnect automatically and resume delivery from the last message it acknowledged.
Clients also maintain a local message database. This allows conversations to load quickly and remain available when the network is temporarily unavailable.
The API Gateway handles conventional requests such as authentication, group management, conversation history, and media upload preparation. It performs rate limiting, request validation, and routing.
Real-time messages do not need to travel through the same request-response path. They are handled by specialised Connection Gateways designed to maintain large numbers of long-lived connections.
A client establishes a persistent connection using a protocol such as WebSockets or a custom protocol over a secure transport.
The Connection Gateway authenticates the device and records where it is connected. A routing entry might map a user and device identifier to a specific gateway instance.
The gateway does not permanently store messages. Its job is to receive commands from clients and deliver events from the backend services.
If a gateway fails, its clients reconnect to another instance and request any messages they missed.
The Message Service is the authoritative entry point for new messages. It checks conversation membership, validates the request, prevents duplicates, assigns ordering information, and stores the message durably.
A successful acknowledgement should only be returned after the message has reached durable storage. This means the platform can recover the message even if a server fails immediately afterwards.
After committing the message, the service publishes an event for delivery workers and other interested components.
The Conversation Service owns conversation metadata and membership. It manages one-to-one conversations, groups, roles, and membership changes.
The Message Service consults authoritative membership information before accepting a message. Cached membership can improve performance, but sensitive changes such as removing a user from a group must be reflected quickly.
Delivery workers consume accepted messages from a partitioned event broker. They determine which devices should receive each message and route it to the correct Connection Gateways.
If a destination device is offline, the message remains pending until the device reconnects or retrieves it from durable storage.
The Presence Service maintains temporary information about active connections, last-seen times, and typing status.
Presence is stored in a fast distributed in-memory system with short expiry times. It is eventually consistent because occasional stale presence information is preferable to placing expensive coordination in the message path.
When a user has no active connection, the Notification Service can send a push notification through the mobile operating system.
The notification should contain minimal information. In an end-to-end encrypted system, the server should not place readable message content in the push payload.
Images, videos, documents, and voice notes are not stored directly in the message database.
The client requests permission to upload a file and then sends the encrypted content directly to object storage. After the upload completes, the client sends a normal message containing a media reference, metadata, and the encryption material required by authorised recipients.
A CDN can distribute the encrypted files efficiently. Only recipient devices possess the information needed to decrypt them.
Synchronous communication is used when the sender needs an immediate result. The Message Service must tell the client whether a message was accepted, rejected, or recognised as a duplicate.
Asynchronous events handle delivery, notifications, analytics, and secondary processing. Once a message has been committed, the Message Service publishes an event to a durable broker.
The broker partitions events by conversation identifier. This ensures that events for one conversation are processed in order while different conversations can be handled in parallel.
The transactional outbox pattern can ensure that every committed message produces an event. The message and its outgoing event are saved as part of the same transaction, after which a background publisher forwards the event to the broker.
This prevents a failure in which a message is stored but never delivered because the server crashed before publishing it.
The central challenges are delivery guarantees, message ordering, offline recovery, group fan-out, and multi-device synchronisation.
The client creates a unique message identifier and stores the outgoing message locally before transmitting it.
The Connection Gateway forwards the request to the Message Service. The service verifies the sender, confirms conversation membership, and checks whether the identifier has already been processed.
If the message is new, the service assigns the next sequence number for the conversation and writes the message to durable storage. It then acknowledges the message to the sender and publishes it for delivery.
The message initially appears as sent on the sender’s device. When a recipient device acknowledges it, the state becomes delivered. A later read receipt changes it to read when the relevant privacy settings permit this.
These status updates are themselves events and must be idempotent.
An unreliable network can lose responses even when the underlying operation succeeds.
Suppose the Message Service stores a message but the connection disappears before the sender receives its acknowledgement. The client cannot know whether the message was accepted, so it retries using the same message identifier.
The service recognises the identifier and returns the original result. It does not create another message.
Internally, the platform can use at-least-once delivery. A message may occasionally reach a device more than once, but the device deduplicates it using the message identifier.
Exactly-once delivery across networks, storage systems, and devices is impractical as an end-to-end guarantee. The combination of durable storage, retries, idempotency, and deduplication gives users the behaviour they expect without claiming an impossible guarantee.
Users expect messages in one conversation to appear in a sensible order. The system does not need to order messages across unrelated conversations.
All message commands for one conversation can be routed to the same logical partition. The partition leader assigns an increasing conversation sequence number before committing each message.
The sequence number provides an authoritative order even when messages arrive from different users or devices at almost the same time.
A client may receive messages out of order because of network delays. It buffers a later sequence briefly while requesting any missing values. If it receives sequence 187 after sequence 185, it knows that sequence 186 must be recovered.
Popular groups can create hot partitions because one conversation cannot be divided freely without weakening its ordering guarantee. The platform can move unusually active conversations onto dedicated processing capacity, but messages within that conversation still require one logical order.
Messages can be stored in a distributed database partitioned by conversation identifier. Within a partition, the conversation sequence number forms the sort key.
This layout supports the most common query: retrieve a range of messages from one conversation in order.
Older messages can be moved into less expensive storage according to the product’s retention policy. A recent-message cache can improve the speed of opening active conversations.
Conversation metadata and membership may remain in a relational or strongly consistent store because these records require constraints and transactional updates.
The platform should not create a separate copy of every message for every recipient unless the delivery model requires it. The durable conversation log can contain one message, while separate per-device cursors record how far each device has progressed.
Each device maintains a delivery cursor representing the highest conversation sequence it has processed or a set of stream offsets representing its progress.
When a device reconnects, it authenticates and supplies its last known cursor. The system retrieves the missing messages and sends them in manageable batches.
The device acknowledges successful receipt so the platform can advance its delivery state. Messages should not be removed simply because one device received them, since the same user may have another device that is still offline.
Push notifications are a wake-up mechanism rather than the source of truth. A device always retrieves the authoritative encrypted messages from the messaging platform after reconnecting.
A user may have a phone, tablet, desktop application, and web session connected at the same time.
Each device is treated as a separate destination with its own identity, encryption keys, connection, and delivery cursor. A message sent from one device should also be synchronised to the user’s other devices so that conversation history remains consistent.
Delivery receipts may represent delivery to any recipient device or to every recipient device, depending on the product requirements. The internal model should retain per-device state even if the user interface shows only one combined indicator.
Adding a new device requires a secure linking process. The device must receive the keys and conversation state it is authorised to access without allowing the server or an attacker to impersonate the user.
For a small group, the system can expand an accepted message into delivery tasks for every member. This is fan-out on write.
The original message is stored once in the conversation log. Delivery workers create routing tasks for the connected devices belonging to current group members.
For very large groups or broadcast channels, generating millions of delivery tasks for every message may be too expensive. The system can instead store the message once and allow members to retrieve it using their conversation cursors. This is closer to fan-out on read.
Membership changes require careful ordering. A user removed from a group must not receive messages created after the removal. Membership updates can therefore be part of the same ordered conversation event stream as ordinary messages.
With end-to-end encryption, messages are encrypted on the sender’s device and decrypted only on recipient devices. Messaging servers store and transport ciphertext rather than readable content.
Each device has an identity key and a set of supporting keys used to establish encrypted sessions. The platform distributes public key material but should never receive the private keys needed to decrypt messages.
One-to-one conversations can establish an encrypted session between the sender and each recipient device. Groups may use sender keys or another group-key mechanism to avoid encrypting every message separately for every participant.
When group membership changes, the encryption state may need to change so that removed members cannot decrypt future messages and new members cannot automatically decrypt earlier history.
Media files are encrypted by the client before upload. The resulting message contains the encrypted file reference and the information authorised recipients need to decrypt it.
End-to-end encryption protects content, but it does not hide all metadata. The platform may still know which accounts communicate, when messages are sent, which devices are connected, and the approximate size of each message. Metadata collection and retention should therefore be minimised.
Presence information is temporary and does not need durable message-level guarantees.
When a device connects, its gateway periodically renews a short-lived presence record. If those renewals stop, the record expires and the user is considered offline.
Typing indicators are transmitted as ephemeral events. They can be routed directly through the real-time infrastructure without being added to the permanent conversation history.
These features should degrade gracefully. If the Presence Service becomes unavailable, users should still be able to send and receive messages.
Privacy settings must also be respected. Some users may choose not to reveal their online status, last-seen time, or read receipts.
Clients should connect to a nearby region to minimise network latency. Global traffic routing can direct them to the closest healthy cluster.
Each conversation can have a home region responsible for assigning its sequence numbers and accepting writes. Messages from other regions are routed to that home region before being committed.
This approach simplifies ordering but adds latency when participants are far from the conversation’s home region. The home region can be chosen based on where the conversation was created or where most participants are located.
Message data is replicated to another region for disaster recovery. During a failover, the platform must ensure that only one region acts as the writer for a conversation. Allowing two regions to assign overlapping sequence numbers would create conflicting histories.
The system may temporarily pause writes to affected conversations while leadership is transferred. Preserving a consistent message history is more important than accepting writes from two uncertain leaders.
Read replicas and regional caches can still provide fast conversation history without becoming authoritative writers.
Connection Gateway failures are expected. Clients should reconnect automatically, authenticate again, and resume delivery from their last acknowledged position.
Message Service instances are stateless and can be replaced behind a load balancer. Durable state remains in the message and conversation stores.
Databases and event brokers should be replicated across availability zones. Automatic failover is useful, but the system must prevent split-brain behaviour in which two nodes believe they are the authoritative writer for one partition.
Consumers must be idempotent because events can be delivered more than once. Delivery workers, notification services, and receipt processors should all recognise previously processed event identifiers.
Backpressure is also important. If recipients are offline or downstream workers become slow, the event broker must absorb a temporary backlog. Queue depth and processing delay should be monitored so capacity can be increased before users notice significant delivery delays.
Non-essential features should fail independently. A problem with presence, typing indicators, notifications, or analytics must not prevent durable message acceptance.
Users and devices must authenticate before establishing a messaging connection. Access tokens should be short-lived, and devices should be removable if they are lost or compromised.
Transport encryption protects connections even though message content is already encrypted end to end. Sensitive keys should remain in secure storage on user devices.
The platform should apply rate limits to account creation, group invitations, message sending, and media uploads. Additional systems can detect spam, automated abuse, compromised accounts, and unusual messaging patterns.
End-to-end encryption makes server-side content inspection difficult by design. Abuse-reporting mechanisms may allow a user to deliberately submit selected decrypted messages and their context for investigation.
Authorisation is required for every conversation operation. Knowing a conversation or message identifier must not allow an unrelated user to retrieve its ciphertext or metadata.
The system should monitor active connections, connection failures, authentication errors, message acceptance latency, database write latency, event broker delay, delivery latency, and push-notification failures.
Delivery measurements should distinguish between server acceptance, delivery to a device, and reading by a user. These are separate stages and may fail for different reasons.
A correlation identifier can follow a message through the Connection Gateway, Message Service, durable store, event broker, delivery worker, and destination gateway. Logs must avoid recording decrypted message content or sensitive encryption material.
The platform should also monitor hot conversation partitions, offline delivery backlogs, duplicate events, missing sequence requests, and regional replication delay.
Business-level monitoring can reveal problems before ordinary infrastructure alerts. A sudden reduction in successful message deliveries may indicate a routing or connection issue even when server health appears normal.
During the interview, begin by defining which messaging capabilities are in scope. Clarify whether the design includes groups, media, multi-device support, delivery receipts, and end-to-end encryption.
Next, explain the difference between conventional API traffic and real-time messaging connections. Clients use an API Gateway for account and history operations while Connection Gateways maintain persistent communication with online devices.
Walk through a message from the sender to the recipient. The Message Service validates and deduplicates the request, assigns its conversation order, stores it durably, acknowledges the sender, and publishes an event for delivery.
The deep dive should focus on guarantees. Messages are durably accepted before acknowledgement, ordered within each conversation, delivered at least once internally, and deduplicated by clients. Offline devices recover missing messages using their delivery cursors.
Be explicit that presence, typing notifications, and live receipts are less critical than message storage. These features can be eventually consistent and should fail without interrupting the core messaging workflow.
Finish by connecting the architecture back to the requirements. The system supports web, mobile, and desktop clients, provides low-latency online delivery, recovers messages after disconnections, scales conversations independently, and protects content with end-to-end encryption.
The platform could be expanded to support voice and video calls using peer-to-peer media where possible and relay servers where direct communication is unavailable.
Disappearing messages could introduce retention rules that remove content from devices and server storage after a configured period. Encrypted backups would allow users to restore history without giving the platform access to readable messages.
Public channels and very large communities would require a different fan-out model from ordinary groups. Messages could be stored once and distributed through regional caches or retrieved by subscribers using ordered cursors.
The system could also add reactions, message editing, threaded replies, scheduled messages, live location sharing, and collaborative features.
More advanced abuse prevention could examine account behaviour, device reputation, message frequency, and user reports without weakening end-to-end encryption.
As the platform expands globally, conversation placement and regional failover could become more adaptive. The system might move a conversation’s home region when its participant distribution changes, provided the transfer preserves ordering and avoids accepting writes in two regions simultaneously.
A messaging platform combines persistent client connections, durable message storage, real-time delivery, offline recovery, group fan-out, and end-to-end encryption.
Web, mobile, and desktop clients connect through API and Connection Gateways. The Message Service validates, deduplicates, orders, and stores each message before acknowledging it to the sender.
Messages are ordered within a conversation rather than globally. A partitioned event broker allows different conversations to scale independently while preserving the sequence of events for each conversation.
Delivery uses at-least-once processing combined with idempotent services and client-side deduplication. Offline and reconnecting devices retrieve missing messages using durable cursors.
The platform stores media separately in object storage and distributes encrypted files through a CDN. Presence and typing events use a faster, temporary path because they do not require message-level durability.
The most important design principle is to separate the authoritative message history from its delivery. Connections may fail, devices may be offline, and events may be retried, but an accepted message remains durable and recoverable.
That distinction allows the platform to provide the experience users expect: messages that arrive quickly when possible and are not silently lost when the network is unreliable.