Scaling real-time messaging across the planet
Slack’s real-time messaging infrastructure bears a loose resemblance to a satellite broadcast system: messages are sent upward to a central service, then fanned out across the globe to millions of connected clients. On a typical workday, traffic peaks twice per region—once in the late morning and again in the early afternoon—but those peaks don't align across regions. The system must handle concurrent prime-time load in North America, Europe, and Asia simultaneously.
The core services that power this are all Java-based and fall into four categories: Channel Servers (CS), Gateway Servers (GS), Admin Servers (AS), and Presence Servers (PS).

Core server roles
Channel Servers are stateful and in-memory, storing a bounded history for each channel they own. Channels here are abstract entities—each ID maps to a user, team, enterprise, file, huddle, or Slack channel. Consistent hashing assigns each channel to a specific CS host, and at peak, each host serves roughly 16 million channels. A single team’s channels are spread across the entire CS pool.
Consistent hash ring managers (CHARMs) maintain the ring and can swap out an unhealthy CS in under 20 seconds. Because each host serves only the channels of a small number of teams, a replacement causes elevated message latency for those teams for less than 20 seconds.

Gateway Servers hold user state and websocket subscriptions. They are the only servers deployed across multiple geographical regions, letting clients connect to the nearest edge. A draining mechanism handles region failures by shifting users to the closest healthy region.
Admin Servers are stateless and in-memory, bridging the Webapp backend and the CS layer. Presence Servers track which users are online; they power the green presence indicators. Clients query presence through the websocket with GS acting as a proxy, and each client only receives presence updates for the subset of users currently visible on screen.
Client connection setup
Establishing a websocket connection follows a straightforward sequence:

The client first fetches a token and connection metadata from Webapp, the Hacklang API backend. It then opens a websocket to the nearest edge region. Envoy terminates TLS and forwards the request to a GS. The GS pulls the user’s full channel list from Webapp, sends the initial state message, and asynchronously subscribes to every CS that hosts those channels, using the same consistent hash ring. From that point, the client can send and receive real-time traffic.
Message fan-out
Broadcast amplification—the ratio of received to delivered messages—varies by region, reflecting differences in team sizes and activity patterns.

The path for a chat message is:
- The client calls the Webapp API to post a message.
- Webapp forwards it to an AS.
- The AS identifies the CS for the channel via the consistent hash ring and routes the message there.
- The CS broadcasts to every GS across all regions that is subscribed to that channel.
- Each GS delivers the message to every connected websocket subscribed to that channel.

Events and transient notifications
Beyond chat messages, the real-time stream carries hundreds of event types that update client state: reactions, bookmark additions, and membership changes, to name a few. Events follow the same routing path as messages. Message volume shows regular spikes at the top of each hour, caused by scheduled messages, reminders, and calendar notifications firing simultaneously.

A separate category, transient events, is never persisted to the database. Typing indicators are the most visible example. These bypass Webapp entirely and travel over the websocket through the GS—the GS routes the event to the appropriate CS, which fans it out to every other GS subscribed to the channel, and those GSs in turn deliver it to all connected websocket clients.


Scale and future direction
The current architecture serves tens of millions of channels per host and tens of millions of connected clients, with cross-region message delivery in under 500ms. The consistent-hash based design scales linearly; each CS simply needs to handle its own share of channels and broadcasts. The team is now focused on extending the system to accommodate future growth without sacrificing the latency guarantees that real-time communication depends on.



