On November 14th, 2025, WhatsApp started letting people in Europe chat with people who are not on WhatsApp. The Digital Markets Act forced the door. Two services walked through it first — BirdyChat and Haiket — with text, images, voice notes and files, and group chats promised later.
Now read the part that didn’t make the headline. Here is Meta’s own engineering blog describing how those third-party clients connect: using “our protocol (based on the Extensible Messaging and Presence Protocol – XMPP)”.
So the protocol everyone spent a decade eulogizing is the protocol the EU’s interoperability mandate now runs on. It didn’t lose. It got absorbed, renamed, and wrapped in an NDA — which is precisely what the XMPP Standards Foundation told Meta in an open letter in March 2025: federation already solves this, and a separate API bridge per provider doesn’t.
That’s the last twenty years in one paragraph. Not “open lost to closed.” The open thing kept running. We just stopped being allowed to point at it.
Read the acronym
eXtensible Messaging and Presence Protocol.
Presence is in the name, one word from the top. Not as a feature. As a peer of messaging.
Strip away the green-dot iconography and here is what presence actually asks: is this identity reachable right now, on which endpoint, and how attentive is it? Online. Away. Typing. Delivered. Read. And underneath all of it an address — vladimir@somedomain.rs — that a server owned by someone else can route to without asking permission from anyone.
Online, typing, receipts and a federated address are not four chat features. They are one primitive: live, addressable, cross-domain identity. Email solved the addressable half in the eighties and never touched the live half. XMPP solved both in 1999.
Then we spent two decades building applications that each rebuilt the live half privately, behind a login, and sold it back as a differentiator.
You don’t have a presence. You have eleven of them, and none of them can see each other.
How the doors closed
The timeline is short, and it isn’t a conspiracy.
- 2005–2006 — Google Talk ships on XMPP, then opens server-to-server federation. You can add a contact from a server Google doesn’t own.
- 2010 — Facebook Chat opens an XMPP endpoint. For a few years the two largest chat networks on the planet speak a standard.
- May 2013 — Google announces it is dropping XMPP federation. The EFF’s headline at the time: Google Abandons Open Standards for Instant Messaging.
- 2015 — Google and Facebook both finish the job.
- 2018 — Slack closes its IRC and XMPP gateways. Stated reason: threads, shared channels and emoji reactions couldn’t be expressed through them.
- Discord never opened one at all.
Read the Slack line again, because it’s the honest one. That gateway didn’t die of malice. It died of product escalation. Slack kept adding surface — reactions, threads, shared channels, presence-aware everything — and the standard modelled none of it, so the bridge became a liar. That’s a real engineering reason. It is also exactly how a protocol becomes a platform: you outgrow the interop layer one feature at a time, and one day deleting it is just housekeeping.
But notice what the housekeeping protects. The moment presence lives behind a login, it stops being a signal and starts being a retention lever. The green dot is how an app tells you the party is inside its building.
Matrix isn’t the sequel. It’s a different bet.
The usual framing is that Matrix picked up where XMPP fell over. That’s not what happened. Matrix made a different architectural wager, and almost everything people argue about downstream — latency, hosting cost, who can see what — falls out of that one decision.
XMPP’s server is a router. A stanza arrives, gets routed to a local session or handed to another domain over server-to-server, and the server is done with it. Conversation state lives at the edges — in your client, in an archive you opted into. The server’s job is delivery, not memory.
Matrix’s server is a replica. A room is an event DAG, and every participating homeserver holds a copy of it and runs state resolution to agree on what “now” means. Not a copy of the messages addressed to its users. A copy of the room.
routes")] SA -->|server-to-server| SB[("b.org
routes")] SB --> B["bob@b.org"] end R ~~~ M subgraph M["Matrix · replicate and resolve"] direction LR HA[("a.org
full room copy")] <-->|"event DAG + state resolution"| HB[("b.org
full room copy")] HB <--> HC[("c.org
full room copy")] HA <--> HC end
In one, state lives at the edges. In the other, state is the product. Where state sits is an architectural surface, not an implementation detail.
That bet buys real things. History survives a dead host. You join a room months late and read everything, with no central server involved. Multi-device sync is a property of the design rather than a bolt-on. If you want Slack shape without Slack ownership, this is the coherent way to get it.
And it costs exactly what replication always costs. Your server now stores and computes rooms it has no business caring about. Synapse doesn’t hide this — it measures a room’s “complexity” as current_state_events / 500 and will refuse to join past a threshold, because the cost is state resolution, not message volume. Operators report a single large federated room pinning about a third of a twelve-core box days later, while everyone is idle. The whole Sliding Sync effort in Matrix 2.0 exists because opening the app meant reconciling all of that first.
Then the punchline. The feature Matrix turned off is the P.
Presence has been disabled in essentially every large deployment because of what it costs. And the maintainers are blunt about why: it’s trivial for a centralized service, but federation makes it combinatorial. The protocol that replicates everything cannot afford the cheapest signal in the system.
Presence is expensive in both worlds, and that’s the actual lesson
This isn’t a dunk. XMPP doesn’t get presence for free either — broadcast to a roster is fan-out, and fan-out is where messaging systems go to die.
The lesson is about shape. Presence is high-frequency, fan-out-heavy, and worth nothing at rest. It expires in seconds. It tolerates loss. Nobody has ever needed to audit last Tuesday’s typing indicators. Replication is the wrong storage model for a fact with a thirty-second TTL, and durable consistency is the wrong guarantee for something that is stale before it’s committed.
Both protocols eventually admitted the other one had a point. XMPP grew Slack-shaped state — archives with MAM, multi-device fan-out with Carbons, and MIX, which quietly makes presence subscription optional in group channels. Matrix spent years making sync cheap enough to feel live. They converged on each other’s problem from opposite directions. Neither of them made presence free, because presence isn’t a chat feature you can architect around. It’s a tier.
Which is why all the arguments people actually have — who is admin in your room, OMEMO versus Megolm, who gets to see that you’re online — are downstream of the fork. They’re consequences of where the state sits. They are not, on their own, a reason to pick a messenger.
So what do you actually build in 2026
If you need federated identity plus a cheap live signal and you don’t need shared history: XMPP. Not for nostalgia. Because it’s still in production at a scale most architectures never touch — ejabberd sits behind WhatsApp, Nintendo Switch’s push infrastructure and the BBC, and Riot Games built League’s chat on it. Prosody and MongooseIM are both live options.
If you need Slack-shaped rooms with decentralized history that survives a host disappearing: Matrix — and budget for it honestly. It is a replicated database with a chat client attached. Run it like one. Then decide, deliberately, whether you’re turning presence on — and write the decision down, because presence: off with no rationale attached reads like an oversight to whoever inherits it.
If your chat only ever happens inside your own product, don’t buy a federation bill you’ll never use. And don’t reach for a document store either — that’s a different post, and the punchline there is the same one: presence is the thing you cannot bolt on afterwards.
The rule I’d actually write down: presence is its own tier, with its own SLO — ephemeral, loss-tolerant, and never in the durable path. If “is Vladimir online?” touches the same store as your message history, you’ve already made the mistake both protocols spent twenty years learning about.
The receipt
The DMA didn’t resurrect XMPP. It just forced a receipt — and receipts outlive the arrangements that produced them. A regulator made Meta write the protocol’s name down in public, and there it was, running the whole time, one abstraction layer beneath the walled garden.
Presence should have been a dial tone. Something you pick up, that just works, that reaches anyone regardless of who sold them their phone. Instead every app sells you its own dial tone, and it only rings inside that building.
That’s not a comeback story. It’s a bill we’re still paying.