How a Discord-like community platform might evolve
Servers with a million members, voice rooms where every millisecond counts, and trillions of stored messages. How massive fan-out, voice over UDP and WebRTC, message storage at scale and presence shape a community platform.
The user problem and the hard parts
A community wants a place to hang out: text channels that feel live, voice rooms where you can talk over each other naturally, and the comfort of seeing who is online. Some communities are a few friends; some (game or creator servers) have hundreds of thousands of members online at once.
The hard engineering problems:
- Massive fan-out: one message in a huge "guild" (Discord's internal term for a server) may need to reach hundreds of thousands of connected clients. Presence changes ("X came online") are even more frequent than messages.
- Voice: humans notice conversational delay above roughly 150–200 ms. Voice must use , tolerate packet loss, and route through servers close to participants.
- Message storage at scale: an append-heavy workload of enormous volume, where reads are mostly "latest messages in this channel" but old messages must stay available forever.
- Presence: online/idle/in-game status for every member, which changes constantly and is visible to many people.
- Hot partitions: one giant community can concentrate load on a single partition of any system.
How the architecture might evolve
A plausible architecture for a community chat and voice platform at each scale. Discord has publicly described using Elixir for real-time fan-out, moving message storage from Cassandra to ScyllaDB, and its WebRTC-based voice servers; other details are illustrative.
- 1
Stage 1 · Gamers and friends
100k users · small serversDesktop/web client with WebSocket gatewayAPI monolithDocument or relational database for messagesVoice servers using WebRTCCDN for avatars and attachmentsSmall guilds make fan-out trivial. Voice uses WebRTC from day one because browsers support it and it handles NAT traversal and codecs.
- 2
Stage 2 · Breakout growth
10M users · guilds of 10k+Gateway tier holding sessionsPer-guild process that owns state and fan-out (Discord publicly describes Elixir/BEAM processes)Messages moved to a wide-column database (Cassandra) partitioned by channel and time bucketRegional voice serversObject storage for attachmentsA lightweight process per guild keeps its member list and fans out events. A wide-column store suits the append-heavy, time-ordered message pattern far better than a single relational primary.
- 3
Stage 3 · Massive communities
100M+ users · guilds of 1M membersFan-out relays that split a giant guild's subscribers across many processesLazy member lists and presence for large guildsMessage store migrated to ScyllaDB (publicly described) with a request-coalescing data service in frontVoice server selection by region and loadOne process per guild becomes the bottleneck for the largest guilds, so fan-out is spread out. Coalescing identical concurrent reads protects hot partitions when everyone opens the same channel after an announcement.
- 4
Stage 4 · Platform
Global · bots, streaming, activitiesBot and integration API with sharded gateway connectionsVideo and screen sharing on the voice infrastructureTrust and safety pipelines on messages and mediaData platform for recommendations and abuse detectionBots connect to the gateway like clients and must be sharded too. Moderation becomes a core system because large open communities attract abuse.
Text fan-out and the voice path
A plausible architecture for Stage 3 might look like this. Text and voice share identity and permissions, but their data paths are completely different.
Click any component to see what it does.
Engineering trade-offs
Relational primary for messages
- Familiar, transactional, flexible queries
- Single-writer limits
- Huge tables and indexes; costly vacuuming and migrations
Wide-column store partitioned by channel + time
- Horizontal write scaling
- Recent-history reads hit one partition
- Limited query patterns (design tables per query)
- Hot partitions in busy channels
- Compaction and repair to operate
Peer-to-peer voice
- No server cost
- Lowest latency for two people
- Each participant uploads to everyone: bandwidth explodes with group size
- Exposes users' IP addresses
SFU voice servers
- Each client uploads once
- Hides IPs, enables moderation features
- Server bandwidth and a global fleet to run
Practical exercise
The @everyone announcement
A game studio posts a launch announcement with @everyone in its 800,000-member guild. Within 5 seconds, 200,000 clients open the channel and request its latest 50 messages, and the same partition in the message database is hammered. Why does this hurt, and how would you design around it?