How WhatsApp Actually Works
A deep dive into WhatsApp's architecture, the decades-old telecom language behind its massive concurrency, the 'let it crash' philosophy that keeps it running through failures, and how a team of around 50 engineers served hundreds of millions of users.

Somewhere around 2014, WhatsApp was reportedly running its entire backend hundreds of millions of users, tens of billions of messages a day with a core infrastructure team you could count on two hands. Most companies handling that kind of scale employ engineering organizations numbering in the thousands. WhatsApp did it with barely 50 people on the whole backend, and fewer than a dozen focused purely on core infrastructure.
That's not a story about hiring geniuses nobody else could find. It's a story about picking unusual, unfashionable tools for exactly the reasons they were originally built, and then having the discipline to keep the whole system simple rather than letting it sprawl. This article walks through how that architecture actually works the decades-old language at its center, the philosophy that treats failure as something to design around rather than avoid, and the deliberately boring choices that let a small team run something enormous. Most of this is drawn from independent engineering breakdowns and public interviews rather than an official WhatsApp engineering blog, since the company has historically published much less about its internals than most of the platforms in this series.
The Language Built for Phone Switches, Repurposed for Chat
The single biggest architectural decision behind WhatsApp is a programming language most developers have never written a line of: Erlang. A breakdown on Ajit Singh's engineering blog explains why this choice mattered so much Erlang was created by Ericsson in the 1980s for telephone switches, systems that needed 99.999% uptime, or roughly five minutes of downtime a year. A phone network genuinely cannot afford to drop your call because of a software bug, and Erlang was built from the ground up around that exact requirement.
A messaging platform turns out to share a strikingly similar shape with a phone network: an enormous number of users, each holding open a connection, each expecting near-instant delivery, with individual failures that absolutely must not cascade into a wider outage. WhatsApp's founders recognized that resemblance and built on top of it, rather than reaching for whatever web framework happened to be popular at the time.
Why One Server Can Hold Millions of Open Connections
Here's the number that tends to stop people mid-sentence the first time they hear it: a single server, running Erlang, can handle 2 to 3 million simultaneous connections. A deep dive on GetStream's engineering blog explains the mechanism directly each connection is just a lightweight Erlang process, and traditional architectures relying on threads or connection pools would need roughly 100 times more servers to handle the same load.
The key detail is what "lightweight" actually means here. A write-up on ScaleWithChintan explains that Erlang processes are measured in kilobytes of memory, not megabytes, and can run in parallel without sharing memory with each other, following a design called the actor model. A separate Medium breakdown on WhatsApp's system design puts a concrete figure on this: each connection uses roughly 2 kilobytes of memory, which is why millions of them can coexist on a single machine without buckling.
A regular operating system thread typically reserves megabytes of stack space just to exist, whether it's doing anything or not. Ten thousand of those threads would already strain most servers. Ten million Erlang processes, each sipping a couple of kilobytes, barely register by comparison and that gap in resource efficiency is the entire reason WhatsApp's server count stayed so low for so long.
Traditional thread-per-connection model:
Each connection ≈ megabytes of memory
10,000 connections → server under real strain
Erlang process-per-connection model:
Each connection ≈ 2KB of memory
2-3 million connections → one server, comfortablyWhat Actually Happens When You Send a Message
The routing logic itself, once you strip away the scale, is refreshingly simple. The same Medium breakdown describes it plainly: when a message arrives, the server checks whether the recipient is currently online. If they are, the message gets delivered directly to their active connection, and the sender is notified it was delivered. If they're offline, the message gets stored in a queue, a push notification is sent to wake up their device, and the sender is simply told it was sent, not yet delivered.
Message arrives at the server
→ Is the recipient currently online?
Yes → Deliver directly to their live connection
→ Notify sender: "delivered"
No → Store the message in a queue
→ Send a push notification to wake their device
→ Notify sender: "sent" (not yet delivered)A critical detail sits underneath this entire flow, and the same source is direct about it: the server never decrypts the message. It only ever routes and tracks the delivery status of an encrypted payload it cannot itself read. A follow-up piece on Medium by Harshavardhan Mamidipaka reinforces this servers only ever see encrypted blobs, never plaintext messages, which means the routing logic above has to work entirely on metadata (who it's for, whether they're online) without ever peeking at what's actually being said.
Mnesia: Keeping Routing Decisions in Memory, Not in a Database
A breakdown on GetStream notes that WhatsApp's core architecture avoids a lot of the moving parts other messaging systems rely on no separate message queue system, no external database purely for routing decisions. Instead, routing state lives in Mnesia, Erlang's own built-in, distributed, in-memory database, running as a natural extension of the same platform handling the connections themselves.
The same source frames the payoff plainly: whether WhatsApp has 1 million or 1 billion users online at a given moment, a message takes the same route through the same in-memory operations. There are no queues to back up under load and no separate database calls to slow things down, which is exactly what keeps delivery consistently fast regardless of how much traffic the system is currently under.
Sending a physical letter through a postal system with multiple sorting facilities, forwarding depots, and handoff points versus handing a note directly to someone standing next to you the second path has fewer places for something to go wrong or slow down, precisely because there are fewer separate systems involved in the handoff at all. Keeping routing decisions in the same in-memory space as the connections themselves is WhatsApp's version of that shorter path.
"Let It Crash": Designing for Failure Instead of Preventing It
Here's a philosophy that sounds almost irresponsible until you understand what it actually means in practice. A write-up on ByteByteGo explains that system failures at WhatsApp's scale weren't treated as unexpected events to be prevented at all costs they were treated as inevitable, and the architecture was built to keep going when things went sideways rather than to pretend they never would.
The same source explains the mechanism: every connection, session, and internal task runs as a lightweight, isolated process managed by the BEAM virtual machine, and dedicated supervisor processes monitor these workers, automatically restarting any that fail. Erlang's "let it crash" philosophy means a failure is contained and doesn't propagate outward across the rest of the system.
A restaurant kitchen where one cook briefly stepping away from their station doesn't shut down the entire restaurant another cook, or a supervisor, notices the gap and covers it almost immediately, and customers at other tables never even notice the hiccup happened. That's the practical effect of a supervisor restarting one crashed process among millions: the failure is real, but it's isolated and repaired almost instantly, rather than being allowed to take anything else down with it.
A process crashes (bug, bad input, unexpected state)
→ Supervisor process detects the crash
→ Supervisor restarts just that one process
→ All other processes continue completely unaffected
→ No cascading failure, no wider outageOver 40 Clusters, Each Doing One Job
A piece on Talent500 describes WhatsApp's backend as divided into more than 40 separate clusters, each one responsible for a specific function message queues, authentication, spam filtering, and more. This logical decoupling limits how far any single failure's blast radius can spread, speeds up development since teams can work on one cluster's function without stepping on another's, and lets each cluster's hardware be tuned specifically for the job it's actually doing, rather than every service being forced onto identical, one-size-fits-all machines.
A large office building where the mailroom, the server room, and the reception desk are all separate, purpose-built spaces rather than one giant open room trying to serve every function at once each space gets exactly the equipment and layout its specific job actually needs, and a problem in one doesn't necessarily spill into the others.
Vertical Scaling First, Horizontal Scaling Second
Here's a genuinely counterintuitive lesson buried in WhatsApp's story, and it runs against a lot of conventional scaling wisdom. The same Ajit Singh breakdown makes the point directly: before adding more servers, WhatsApp pushed each individual server to handle over 2 million connections, because vertical scaling making each individual server do more is often simpler to reason about than horizontal scaling, which means adding more machines and coordinating between them.
Only once a single server was already handling millions of connections did adding more Erlang nodes to the cluster become the next lever, and a piece on Software Patterns Lexicon notes that Erlang's built-in distribution capabilities make connecting additional nodes into the cluster relatively seamless once that point is actually reached. Squeezing far more capacity out of each individual machine first meant far fewer machines needed to be coordinated at all fewer network hops between servers, fewer places for a distributed system's usual coordination headaches to creep in.
Staying Alive Through Genuine Chaos
The real test of an architecture built around inevitable failure is what happens during an actual, large-scale incident. The same Harshavardhan Mamidipaka piece describes WhatsApp's resilience toolkit: multi-region active-active servers, automatic reconnection using exponential backoff, persistent TCP reconnect logic, hot code reloads that don't require restarting a running system, transparent failover, distributed retry queues, and backpressure mechanisms to avoid being overwhelmed by a sudden flood of reconnecting clients.
The same source points to the October 2021 Facebook infrastructure outage a global DNS-related incident that took down Facebook, Instagram, and WhatsApp simultaneously as a real demonstration of this design working under pressure: WhatsApp recovered gracefully specifically because of its strong reconnection logic, rather than requiring a slow, manual recovery process once the underlying issue was fixed.
A phone that automatically keeps trying to reconnect to Wi-Fi after you walk back into range, gradually spacing out its retry attempts rather than hammering the network constantly, is the same basic idea behind exponential backoff and multiplied across hundreds of millions of devices simultaneously reconnecting after a global outage, having that retry logic staggered rather than synchronized is the difference between a smooth recovery and a second, self-inflicted outage caused entirely by the flood of reconnection attempts themselves.
Putting It Together
None of the individual pieces here are exotic inventions on their own. Erlang has existed since the 1980s. The actor model is a well-studied concurrency pattern. Supervisor-based crash recovery is a documented, decades-old Erlang/OTP feature. What makes WhatsApp's engineering story genuinely remarkable isn't any single piece it's the discipline to keep choosing the deliberately simple, boring, battle-tested option at every layer, resisting the pull toward trendier technology, and trusting that a small, focused team working within a system this consistent can outperform a much larger team fighting unnecessary complexity.
What This Means Going Forward
As messaging platforms keep adding features multi-device sync, larger group chats, richer media, business integrations the temptation to bolt on more services, more languages, and more moving parts only grows. WhatsApp's story is a useful counterweight to that instinct: the lesson underneath everything in this article isn't really about Erlang, Mnesia, or the actor model specifically. It's the same one running through this entire series: the systems that hold up best under real-world scale are rarely the most complicated ones. They're the ones built around a small number of ideas, chosen deliberately, and trusted enough to keep things simple even as everything around them keeps growing.
Read Next

How Telegram Actually Works
A deep dive into Telegram's architecture, the cloud-native design that syncs your chats across every device, the custom MTProto protocol built for hostile networks, and the radical team-size philosophy that keeps a billion-user platform running on a team you could fit in one conference room.

How Slack Actually Works
A deep dive into Slack's architecture, the Channel Servers, Gateway Servers, and WebSocket connections that deliver messages across the globe in under 500 milliseconds, and the video-game origins that shaped it all.