Telegram's Sticky Home-DC Architecture
A multi-DC messaging platform that prioritizes legal distribution and user affinity over pure geo-latency.
Most hyperscale chat systems treat data centers as interchangeable capacity behind anycast or smart DNS. Telegram does something different. Accounts stick to a home data center, files stay where they were uploaded, and clients spend a surprising amount of their lifecycle handling forced redirects between a small set of independent DCs. That model is not an accident of growth. It is the product of how Telegram assigns users, how it stores media, and how it spreads legal control of cloud chat data across jurisdictions.
For anyone writing an MTProto client, a userbot, or a multi-region pipeline against Telegram's API, the home-DC rules matter more than the public IP list. Latency, auth, and file access all flow from them.
Home DC assignment is sticky on purpose
Telegram runs a decentralized multi-DC footprint (libraries currently document five DCs, each able to operate independently). Some quieter DCs have been retired in practice, with their addresses kept as aliases to remaining capacity. What has not changed is the affinity model.
When an account is created, Telegram picks the home DC. The client does not. Official API docs are explicit: user state accumulates in the DC the user is associated with, so a client cannot re-home an account on its own. Registration and sign-in go through auth.sendCode. About 95% of DC redirects happen on that call.
The redirect path is straightforward:
- If the phone number already exists, Telegram may return
PHONE_MIGRATE_Xso the client reconnects to the DC that owns that account. - If the number is new, Telegram looks at the client IP, picks the nearest DC, and may return
NETWORK_MIGRATE_X. - Later, after prolonged use from an unusual location, Telegram may copy the account and flip affinity. Queries to the old DC then fail with
USER_MIGRATE_Xuntil the client follows.
IP and port endpoints themselves move often with load and client location. Clients are expected to call help.getConfig, read this_dc and dc_options, and prefer the closest access point for ordinary traffic. That is routing optimization around a sticky home, not free placement of user state.
Telegram's own FAQ adds the legal framing: cloud chat data lives in multiple data centers controlled by different legal entities in different jurisdictions, with decryption keys split so they are not co-located. Independent DCs plus sticky accounts are consistent with that design. Pure lowest-latency anycast would fight it.
Files do not follow the user
Media is the other hard edge. A part written with upload.saveFilePart is only directly downloadable from the DC that accepted the upload. Documents, photos, profile photos, chat photos, and encrypted files all carry a dc_id. Download means open an encrypted session to that DC and call upload.getFile. Hit the wrong DC and you get FILE_MIGRATE_X.
Auth material does not ride along for free. Encryption keys are not copied between DCs, so each new DC connection starts the key exchange from scratch. Telegram exposes authorization transfer (auth.exportAuthorization / import) so clients can attach an existing user session to a new DC without another SMS code. Client libraries that skip transfer force users through needless re-auth when they first touch media on a foreign DC.
This is a deliberate split: conversational state is home-DC sticky; blobs are write-local and read-local. Cross-DC messaging still works, but it is not free. Developers have reported multi-second delays receiving channel traffic that originates on a different DC than the subscriber's home, which matches a design where inter-DC fanout is secondary to keeping each DC operationally independent.
What builders actually have to implement
If you are on the Bot API only, most of this is hidden. If you speak MTProto (Telethon, Pyrogram, TDLib, or a custom stack), you own the state machine.
Minimum viable DC handling
- Bootstrap to any known endpoint, then call
help.getConfigand cachedc_options. - On
PHONE_MIGRATE_X,NETWORK_MIGRATE_X,USER_MIGRATE_X, orFILE_MIGRATE_X, tear down, open a fresh encrypted connection to the target DC, and retry. Do not invent your own home-DC preference. - Keep per-DC auth keys. Use authorization transfer when you already have a logged-in session on the home DC and need media from another.
- Treat every
dc_idon aDocumentorPhotoas authoritative for download, not a hint.
Test without burning real numbers. Telegram reserves 99966XYYYY phones (X = DC id, YYYY random). The login code is the DC id repeated five times. Libraries document wiring a fixed DataCenter (for example test IPv4 for DC 2) so you can exercise migrate paths and multi-DC file fetch offline of production accounts.
You still cannot pick production affinity. Registering through a US proxy or reading nearestDC as 1 does not guarantee a DC 1 account if Telegram decides otherwise. Prolonged presence near another region may eventually trigger USER_MIGRATE_X, but that is server policy, not a client API. Workarounds discussed in the wild (foreign virtual numbers, later swapping the phone on the account) sit outside the documented protocol and should not be treated as supported product behavior.
Latency expectations. Same-DC traffic is the fast path. Cross-DC channel and user fanout can lag by seconds under ordinary conditions. If your product needs tight interaction between two accounts (trading bots, multi-account moderation, mirrored channels), put them on the same home DC when you can influence registration, and measure. Do not assume global message bus semantics.
Operational reality. Endpoint IPs change. Hardcoding yesterday's list is fragile; help.getConfig is the source of truth. CDN and media_only options in dcOption exist for a reason: separate media paths from interactive RPC when the config offers them.
Trade-offs against the usual cloud playbook
Compared with a classic multi-region app (write-local, async replicate, client-directed region), Telegram inverts control. The platform chooses home, migrates when it wants, and forces clients to chase files and auth. That costs developer complexity and some cross-region latency. What it buys is independent DC failure domains, simpler per-DC data gravity for accounts, and a story about keys and legal entities that a single global store cannot match.
Competitors that centralize user state and fan media through a global edge put the complexity in the edge and the control plane. Telegram puts it in every serious client. Neither is free. Telegram's choice is coherent once you stop treating the public DC map as a latency menu and start treating it as an affinity and custody system.
Bottom line
Telegram's global footprint is real, multi-homed, and deliberately sticky. Five (or fewer active) independent DCs, home-account affinity, write-local files, and migrate errors as the control plane are the architecture. For client authors that means correct migrate handling, per-DC keys, and authorization transfer are not polish. They are the product. For product engineers it means DC placement is a first-order constraint on multi-account and media-heavy workflows, not an infrastructure detail you can ignore behind a CDN. The mysteries dissolve once you stop looking for anycast and start reading the migrate errors.
Sources & further reading
- Mysteries of Telegram Data Centers — dev.moe
- Working with Different Data Centers — core.telegram.org
- What are the IP addresses of Telegram Data Centers? - PyroTGFork 2.2.24 Layer 225 — telegramplayground.github.io
- Data centers — Telethon 2.0.0a0 documentation — docs.telethon.dev
- Telegram data center switch - Stack Overflow — stackoverflow.com
Ji-ho covers the increasingly tangled overlap between cloud architecture and security, drawing on a background as a penetration tester to keep his reporting grounded in real-world attack paths. He never lets a vendor claim go unquestioned and insists that every buzzword come with a proof of concept.
Discussion 1
another thing to consider when building a chat app, joy