Skip to content

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 Discord-like community platform

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. 1
    Stage 1 · Gamers and friends
    100k users · small servers
    Desktop/web client with WebSocket gatewayAPI monolithDocument or relational database for messagesVoice servers using WebRTCCDN for avatars and attachments

    Small guilds make fan-out trivial. Voice uses WebRTC from day one because browsers support it and it handles NAT traversal and codecs.

  2. 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 attachments

    A 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. 3
    Stage 3 · Massive communities
    100M+ users · guilds of 1M members
    Fan-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 load

    One 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. 4
    Stage 4 · Platform
    Global · bots, streaming, activities
    Bot 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 detection

    Bots 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 a component

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
Choose when: Up to millions of messages per day.

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
Choose when: Append-heavy, time-ordered data at massive volume.

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
Choose when: One-to-one calls.

SFU voice servers

  • Each client uploads once
  • Hides IPs, enables moderation features
  • Server bandwidth and a global fleet to run
Choose when: Group voice and video.

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?