# Frontend System Design: Build Discord

Source: https://www.techinterview.org/post/3233475352/frontend-system-design-build-discord/
Updated: 2026-05-06 · techinterview.org

"Design Discord" is a senior+ frontend system-design prompt that combines real-time messaging, voice/video, presence at scale, and a large client-side state graph. Discord's desktop client is famous for being a heavy Electron app; the frontend interview tests whether you can decompose its features into a clean state architecture.

## Clarify scope

- Servers (guilds), channels, DMs?

- Voice and video channels included?

- Threads, forum channels, stage channels?

- Offline / cached state?

- Cross-platform (desktop + mobile parity) or web only?

## The state graph

Discord's state is large; the most-cited Discord engineering post described moving from Redux-of-everything to a more scoped store. The shape:

- guildsById — Map of all servers the user is in

- channelsById — Map of channels (across all guilds and DMs)

- messagesByChannel — Map of channel ID → (message list, cursor)

- membersByGuild — guild members (often huge)

- presenceByUserId — online state, custom status

- voiceStates — who is in which voice channel, mute, deafen

- readState — last-read message per channel

## Memory matters

A user in 100 servers with 50 channels each can have data for 5,000 channels in memory. Strategies:

- Lazy-load message history per channel; do not preload all

- Drop messages from inactive channels under memory pressure

- Member lists for very large guilds (100K+) are virtualized and lazily fetched

- Discord historically stored a large in-memory cache; modern variants page to disk via IndexedDB

## WebSocket gateway

- Single persistent connection per client

- Receives all events: messages, presence, typing, voice state, member joins

- Sharded server-side; client is unaware

- Heartbeat every 41 seconds (Discord-specific); reconnect with sequence number on disconnect

- Resume protocol replays missed events

## Voice and video

- WebRTC for media; Discord runs custom SFU servers

- Voice channel join: signaling over the gateway, then RTP to the SFU

- Video and screen share are layered on the same SFU

- Krisp-style noise suppression in the client (CPU)

- Voice activity indicator updates every ~30ms during talking

## Channel switching

Snappy channel switch is a Discord differentiator:

- Pre-fetched recent messages for the most-recently-used channels

- Rendered placeholder while paginating older messages

- Compose box state preserved per channel (drafts)

- Typing-indicator state preserved (do not flash)

## Message rendering

- Virtualized list — only visible messages mounted

- Variable-height messages (text, image, embed, code block)

- Markdown rendering with custom Discord syntax (mentions, channel links, custom emoji)

- Edit / delete updates by message ID; tombstones for deletes

- Reactions update the reaction map without re-rendering the message body

## Presence at scale

- Discord delivers presence for the visible member list, not all members

- Subscribe to presence updates for the displayed members; unsubscribe when scrolled away

- For very large guilds, presence is fanned out via lazy queries

## Notifications and unread state

- Per-channel last-read message ID, persisted on the server

- Mention bumps a separate counter

- Per-guild "any unread" derives from channel unread states

- Sidebar shows unread bubbles; navigation marks-as-read

## Threads and forum channels

- Thread = child channel of a parent channel

- Auto-archive after inactivity

- Forum channel = root with many threads, no top-level chat

- State stored in same channel/message maps with a parent link

## The Electron / web split

- Discord desktop is Electron — same codebase as web with native integrations

- Native: push-to-talk hotkey (global), system overlay, autostart

- Web: subset; voice still works, push-to-talk limited

- Mobile: separate React Native codebase

## Offline behavior

- Cached message store in IndexedDB for recently-active channels

- Queued send: messages composed offline are sent on reconnect

- "Reconnecting..." banner; messages sent during disconnect remain optimistic until confirmed

## Performance considerations

- The Discord engineering post about reducing CPU on the message list is a classic; rendering tens of messages efficiently matters

- Memoize messages by ID

- Avoid context that re-renders entire trees on small updates

- Profile with React DevTools; focus on the most-mounted components

## What separates senior from staff

Senior candidates draw the state shape and discuss virtualization. Staff candidates address memory pressure across thousands of channels, the WebSocket reconnect/resume protocol, and the lazy-presence subscription model. Principal candidates raise the cross-platform architecture (web/desktop/mobile) and the platform-specific tradeoffs.

## Frequently Asked Questions

### How does Discord handle a guild of 1M members?

Member list is lazy and chunked; full member fetch is rate-limited. Presence subscriptions are scoped to the visible window. The client never has 1M members in memory at once.

### What about end-to-end encryption?

Discord does not E2E-encrypt by default (server-readable for moderation). Voice DM E2E encryption was added recently. If asked about E2E DM design, see the Signal-style mobile system design question.

### Why is the desktop app heavy?

Electron + the size of state + voice processing. There is no fundamental fix; the team has reduced memory and CPU significantly over the years but the architecture has costs.
