DEV Community

RONI DAS
RONI DAS

Posted on • Originally published at systemdesign.academy

How Telegram Delivers Messages to Million-Subscriber Channels

Telegram has two jobs that pull in opposite directions. A private chat needs to sync perfectly across your phone, laptop, and tablet, with every message in order and nothing lost. A public channel needs to take one post and deliver it to millions of subscribers without melting the servers. The same product, two very different delivery problems.

The core problem

Cloud messaging means the server is the source of truth, not the device. Unlike a model where the device holds all state, here messages live on the server so any device can pull the full history and stay in sync. That makes multi-device easy but puts the load on the backend, and it means the server needs a way to tell each device exactly what it has and has not seen.

Channels break the usual chat assumption. A normal group has tens or hundreds of members, so you can afford to write a copy of each message to every member. A channel can have millions of subscribers. Writing a copy per subscriber for every post is a firehose of writes that does not scale.

Key design decisions

Sequence numbers, not timestamps, define order. Each chat has a monotonically increasing message sequence. A device remembers the last sequence it has, and on reconnect it asks for everything after that number. This makes sync a simple range fetch and sidesteps clock skew between devices. Ordering is defined by the server's counter, so all devices converge on the same order.

A per-device update stream. Rather than each device polling every chat, the server keeps a stream of updates per account and each device catches up from its last known point. Miss a few minutes of connectivity and you replay the gap, not the whole history.

Fanout on read for large channels. For a channel, do not copy the post into millions of inboxes. Store the post once in the channel's own message history. When a subscriber opens the channel, they read from that shared history at their last-read position. One write, many reads. This is fanout on read, and it is what makes million-subscriber channels affordable.

Fanout on write for small chats. For private and small group chats, the opposite is cheaper: push the message to each member's update stream immediately so their devices get it in real time without asking. With few members the write amplification is small and the latency win is real.

Push notifications are a separate concern. Waking a sleeping phone goes through platform push services and carries a hint, not the full message. The device then pulls the actual content over the sync channel, which keeps notification payloads small and lets the server stay the source of truth.

The trade-offs

Fanout on write gives instant delivery but its cost grows with membership. It is right for small chats and wrong for huge channels. Fanout on read scales to any number of subscribers but shifts work to read time, so a channel with a sudden spike of readers opening it at once creates a read burst instead of a write burst. Many systems, including this one, use a hybrid: write-fanout for small conversations, read-fanout for large broadcast channels, and pick per chat based on size.

Server-as-source-of-truth makes multi-device sync clean but concentrates load and trust on the backend. It is the reason history is available on a new device instantly, and also the reason the sync and storage layer has to be very robust. Sequence-based sync is simple and correct but assumes a reliable per-chat counter, which the storage layer has to guarantee even under failover.

How the real system does it

The real design keeps messages on the server as the authority, syncs each device with per-chat sequence numbers and a per-account update stream so reconnecting is a cheap range fetch, and splits delivery by scale: small chats fan out on write for low latency, massive channels store the post once and fan out on read. Push services only wake the device, which then pulls the real content.

The general lesson: there is no single correct fanout strategy. Choose write or read fanout based on the ratio of writers to readers, and do not be afraid to run both in the same product.

I wrote the full breakdown, with diagrams and the data model, here: https://www.systemdesign.academy/interview/design-telegram

Top comments (0)