Markdown Editor

Video Conferencing System Design Template (WebRTC SFU)

WebRTC video meetings: mesh vs MCU vs SFU, simulcast layers, bandwidth estimation and layer selection, SFU cascading, raw track recording, SFrame E2EE

시스템 설계전체W3C WebRTC Recommendation (13 March 2025); RFC 3550; RFC 7667; RFC 8853; RFC 8888; RFC 9605designvideoconferencingmath

사용법: Use it when designing or reviewing a multiparty audio and video meeting service, or preparing the video conferencing interview question. Fill the bitrate ladder and receive mix in section 3 first, because SFU egress, not CPU, sizes the fleet. The main pitfall is drawing media and signaling on the same arrows and forgetting that layer switches need key frames.

미리보기

System Design: [Video conferencing service name]

Reference design for a multiparty video conferencing service built on WebRTC: browser and native clients, a signaling service, selective forwarding units (SFUs) with simulcast, bandwidth estimation and layer selection, cascading across regions for large meetings, recording and optional end-to-end encryption. It builds on the W3C Recommendation "WebRTC: Real-Time Communication in Browsers" (13 March 2025), RTP (RFC 3550), RTP topologies (RFC 7667), simulcast (RFC 8853), congestion control feedback (RFC 8888) and SFrame (RFC 9605). It follows the structure of the System Design Document template, adds a 45-minute interview path, access-pattern and failure-mode tables and a cited "How real systems do it" box, and is pre-filled with a worked design to adapt. Replace every [bracketed] value and every row marked Example; values marked Example are assumptions, not benchmarks.

Document control

FieldValue
Document ID[SDD-VC-001]
System / feature[Real-time meetings: audio, video, screen share]
Version[0.1]
Status[Draft / In review / Approved / Implemented / Superseded]
Owner[@owner]
Author(s)[@author]
Reviewers[@reviewer-1], [@reviewer-2]
Last updatedYYYY-MM-DD
Classification[Internal]
DifficultyAdvanced
WebRTC baseline[W3C Recommendation, 13 March 2025]
Related[Live streaming design], [Notification service], [ADR: SFU versus MCU]

Approvals

RoleNameDecisionDate
Tech lead[@name][Approved / Changes requested]YYYY-MM-DD
Staff / principal engineer[@name][Decision]YYYY-MM-DD
Media / real-time engineering[@name][Decision]YYYY-MM-DD
SRE / network operations[@name][Decision]YYYY-MM-DD
Security and privacy[@name][Decision]YYYY-MM-DD

Revision history

VersionDateAuthorChange summary
0.1YYYY-MM-DD[@name]First draft for design review
0.2YYYY-MM-DD[@name]Example: Replaced live composite recording with raw track recording after cost review
0.3YYYY-MM-DD[@name]Example: Added SFU cascading for meetings that span regions
1.0YYYY-MM-DD[@name]Example: Approved

Contents

1. Overview

1.1 Problem statement

[Example: The current product runs small calls as a peer-to-peer mesh. Each participant uploads one copy of its video to every other participant, so a six-person call needs about 7.7 Mbps of upload per person (section 3.2), and calls above four people freeze on home connections. Customers also ask for recording, meetings of several hundred people and an end-to-end encrypted mode for sensitive calls.]

1.2 Proposed solution

[Example: Clients join through a signaling service over a WebSocket and send media to the nearest SFU over WebRTC (ICE, DTLS-SRTP). Each sender publishes three simulcast layers of its camera. The SFU forwards packets without decoding them and picks, for every receiver, the layer that fits the receiver's estimated bandwidth and screen layout. Meetings whose participants are in several regions use one SFU per region, linked by a cascade that carries each layer once between regions. Recording writes the raw forwarded tracks to object storage and composes a playable file after the meeting. An optional end-to-end encrypted mode wraps every frame with SFrame keys that the server never sees.]

1.3 Decisions requested from reviewers

IDQuestionRecommended optionSection
Q-01Example: Mesh, MCU or SFU?SFU for every meeting, including two-person calls, so one code path serves all sizes7.1, 10
Q-02Example: How many simulcast layers?Three layers (180p, 360p, 720p) for camera, one high layer for screen share7.2
Q-03Example: Live composite recording or raw track recording?Raw tracks during the meeting, composite afterwards7.5
Q-04Example: Is end-to-end encryption on by default?Opt-in per meeting; it disables server recording and transcription7.6
[Q-nn][Question][Option][Section]

1.4 45-minute interview path

Use this order when the document serves an interview or a short design review. The written sections below are the long form of each step.

MinutesCoverOutput on the whiteboard
0 to 5Scope: meeting size, audio and video, screen share, recording; below-the-line items (2.3)Three to five core requirements, latency target
5 to 10Estimates: upload per sender, download per receiver, SFU egress, server count (section 3)"Egress, not CPU, sizes the fleet"
10 to 15Interfaces: join API, signaling messages, what travels over RTP (section 4)Join call plus offer, answer and candidate messages
15 to 25High-level design: clients, signaling, SFU, TURN, recording (section 6)One diagram with media and signaling paths drawn apart
25 to 40One deep dive: simulcast and layer selection with bandwidth estimation (default, 7.2 and 7.3), or cascading for large meetings (7.4), or recording (7.5)Options, choice, reason
40 to 45Failures (SFU crash, packet loss, region loss) and the 10x row in section 10Two failure rows

Start the default deep dive with the naive answer, a mesh where every peer sends to every other peer, and show that upload grows with meeting size. Then introduce the MCU, which fixes upload but decodes and re-encodes every stream, and finally the SFU, which only forwards packets but needs the sender to offer several qualities so that each receiver can get one that fits.

2. Requirements

2.1 Core functional requirements

IDRequirementPriority
FR-01Example: Create a meeting, share a link, join from a browser or native appMust
FR-02Example: Two-way audio and video for up to 100 interactive participantsMust
FR-03Example: Screen sharing by one presenter at a timeMust
FR-04Example: Active speaker view and gallery view with up to 25 tilesMust
FR-05Example: Host controls: mute others, remove participant, lock meeting, waiting roomMust
FR-06Example: Cloud recording available within 30 minutes after the meeting endsShould
FR-07Example: Optional end-to-end encrypted meetingsShould
FR-08Example: View-only attendees up to 1 000 per meetingCould
[FR-nn][Requirement][Must / Should / Could]

2.2 Non-functional requirements

IDQualityTargetMeasured as
NFR-01Media latencyExample: Glass-to-glass p95 at or below 250 ms within one region, 400 ms across regionsSynthetic clients with timestamped frames
NFR-02Join timeExample: p95 from click to first audio at or below 3 sClient telemetry
NFR-03AvailabilityExample: 99.95% of meeting-minutes without a media interruption longer than 5 sClient reconnect events
NFR-04Quality under lossExample: Audio remains intelligible at 10% random packet lossNetwork emulation test
NFR-05ScaleExample: 2 million concurrent participants at peakLoad test with synthetic publishers
NFR-06PrivacyExample: Media encrypted in transit on every hop; E2EE mode keeps media keys off serversSecurity review, packet capture
[NFR-nn][Quality][Target][Measurement]

2.3 Below the line (out of scope)

Name these explicitly so reviewers and interviewers do not pull the design toward them.

  • [Example: broadcast to unlimited viewers through a CDN (see the live streaming design)]
  • [Example: telephone dial-in through a PSTN gateway]
  • [Example: live captions and translation (separate speech pipeline consuming audio tracks)]
  • [Example: calendar integration and scheduling user interface]
  • [Item deferred, with the release that will take it]

3. Capacity estimation

3.1 Assumptions

InputSymbolValueSource
Peak concurrent participantsPPExample: 2 000 000Usage forecast
Average interactive meeting sizemmExample: 6Product analytics
Simulcast camera layers (180p, 360p, 720p)bl,bm,bhb_l, b_m, b_hExample: 0.15, 0.5, 1.5 MbpsEncoder settings
Audio bitrate incl. packet overheadaaExample: 0.04 MbpsOpus at about 32 kbps plus headers
Share of participants with camera onccExample: 0.7Product analytics
Receive mix per participantExample: 1 large tile at 720p, 3 small tiles at 180p, 3 loudest audio streamsDefault layout
Usable egress per SFU serverEEExample: 6 Gbps (10 Gbps NIC at 60%)Load test
Average meeting lengthddExample: 45 minProduct analytics

3.2 Why not a mesh

In a mesh each sender uploads its high layer and audio to every other participant:

Umesh=(m−1)(bh+a)=5×(1.5+0.04)=7.7 Mbps per senderU_{mesh} = (m - 1)(b_h + a) = 5 \times (1.5 + 0.04) = 7.7 \ \text{Mbps per sender}

Many home and mobile uplinks cannot sustain this, so a server in the media path is required for meetings above three or four people.

3.3 Upload and download per participant with an SFU

U=c (bl+bm+bh)+a=0.7×2.15+0.04=1.545 MbpsU = c\,(b_l + b_m + b_h) + a = 0.7 \times 2.15 + 0.04 = 1.545 \ \text{Mbps}
D=bh+3 bl+3a=1.5+0.45+0.12=2.07 MbpsD = b_h + 3\,b_l + 3a = 1.5 + 0.45 + 0.12 = 2.07 \ \text{Mbps}

The sender uploads three layers once; the receive mix stays constant as the meeting grows, because the layout caps the number of tiles.

3.4 SFU fleet

I=P×U=2×106×1.545 Mbps=3.09 Tbps ingressI = P \times U = 2 \times 10^{6} \times 1.545 \ \text{Mbps} = 3.09 \ \text{Tbps ingress}
O=P×D=2×106×2.07 Mbps=4.14 Tbps egressO = P \times D = 2 \times 10^{6} \times 2.07 \ \text{Mbps} = 4.14 \ \text{Tbps egress}
N=OE=4 140 Gbps6 Gbps=690 servers,690×1.25≈863N = \frac{O}{E} = \frac{4\,140 \ \text{Gbps}}{6 \ \text{Gbps}} = 690 \ \text{servers}, \qquad 690 \times 1.25 \approx 863

Ingress alone would need 515 servers, so egress is the binding constraint. With 25% headroom for failover and uneven placement the fleet is about 870 SFU servers across all regions. With an average packet of about 1 100 bytes, egress is about 470 million packets per second, about 680 000 per server before headroom, so the forwarding path must avoid per-packet allocation and system calls where possible (batching sends, kernel bypass or large socket buffers).

3.5 Signaling and recording

  • Joins: P/d=2×106/2 700 s≈741P / d = 2 \times 10^{6} / 2\,700 \ \text{s} \approx 741 joins/s on average at peak, about 7 400 joins/s in the minute after the hour when meetings start together. At about 10 signaling messages per join that is about 74 000 messages/s, small for a horizontally scaled WebSocket tier.
  • Recording: if 5% of 4 million daily meetings are recorded, live composite recording at 2.064 Mbps (720p plus 64 kbps audio) writes about 139 TB per day (12.5 PB for 90 days) and needs about 16 700 compositors running at peak, about 33 000 vCPU at 2 vCPU each. Raw track recording of the 360p layers (6×(0.7×0.5+0.04)=2.346 \times (0.7 \times 0.5 + 0.04) = 2.34 Mbps per meeting) writes about 158 TB per day (14.2 PB for 90 days) but needs no live decoding.

3.6 Summary

QuantityEstimateDesign consequence
Mesh upload at 6 people7.7 Mbps per senderServer in the media path from day one
Upload per participant1.545 MbpsSimulcast with three layers is affordable for senders
SFU egress4.14 TbpsFleet sized by NIC egress, about 870 servers with headroom
PacketsAbout 680 000 per server per secondForwarding path optimised for packet rate
JoinsAbout 7 400/s at the top of the hourStateless signaling tier, meeting state in a shared store
Recording139 to 158 TB per dayRaw tracks now, composite later; lifecycle rules on storage

4. API design

4.1 Interfaces

InterfaceOperationPurpose
RESTPOST /v1/meetingsCreate a meeting; returns ID, join link, settings
RESTPOST /v1/meetings/{id}/join-tokensIssue a short-lived signed join token for one participant and role
WebSocketwss://signal.example.com/v1?token=Signaling channel for one participant session
WebRTCICE, DTLS-SRTP, RTP and RTCP to the assigned SFUMedia and media feedback
RESTGET /v1/meetings/{id}/recordingsList recordings and their processing state
Webhookmeeting.ended, recording.readyNotify integrations

4.2 Join flow

The join token is a signed, short-lived credential (for example a JWT with a 60 s expiry) that names the meeting, the participant and the role. The signaling service validates it, picks an SFU (7.4) and returns ICE servers, including TURN credentials that expire with the session.

{"type": "joined", "meetingId": "mtg_7Qx2", "participantId": "p_19", "role": "host", "sfu": {"region": "eu-west", "node": "sfu-eu-w-114"}, "iceServers": [{"urls": ["turns:turn.eu-west.example.com:443?transport=tcp"], "username": "1730300000:p_19", "credential": "[short-lived]"}]}

4.3 Signaling messages

MessageDirectionContent
offer / answerBothSDP per JSEP (RFC 9429), including the simulcast rid list
candidateBothTrickled ICE candidates (RFC 8445)
layoutClient to serverWhich participants the client shows and at what size
track-published / track-removedServer to clientTrack list changes for the meeting
active-speakerServer to clientCurrent dominant speaker from audio levels
host-actionBothMute, remove, lock, admit from waiting room
e2ee-key-epochServer to clientEpoch announcement only; key material never passes through the server in E2EE mode

The layout message matters for capacity: a client that shows only the active speaker should not receive 24 thumbnails it will never draw.

5. Data model

5.1 Entities

Meetings and recordings are durable records; sessions, tracks and SFU assignments are live state that exists only while a meeting runs.

5.2 Storage choices

DataStoreKeyWhy
Meetings, recordings metadataExample: Relational database, replicatedmeeting_idLow write rate, needs transactions for host settings
Live meeting state (sessions, tracks, SFU assignment)Example: In-memory store with replication, per regionmeeting:{meeting_id}Read on every signaling event; lost state can be rebuilt from clients
SFU load registryExample: Service discovery with TTL keyssfu:{region}:{node_id}Heartbeats every 2 s, expire on node loss
Recorded tracksObject storagerec/{meeting_id}/{track_id}/{segment}Large sequential writes, lifecycle rules
Quality telemetryEvent pipeline to analytics storeTime, meetingHigh volume, never on the media path

5.3 Access patterns

Access patternFrequencyKey or index that serves itPartition key rationale
Find the SFU that hosts a meeting in this regionEvery join (about 7 400/s at peak)meeting:{meeting_id} hash, field per regionOne meeting is the unit of placement, so all its state lives under one key
Pick the least-loaded SFU for a new meetingEvery first join in a regionSorted set of nodes by egress load per regionPer-region set; joins never scan other regions
Broadcast a track change to all participantsEvery publish or unpublishMeeting channel on the signaling tier keyed by meeting_idSignaling nodes subscribe to the meetings they serve
List recordings for a meetingRaremeeting_id index in the relational storeJoins with meeting ownership for access checks
Compose a recording after the meetingOnce per recordingObject prefix rec/{meeting_id}/One prefix per meeting lets a worker list every track in one call
Analyse call quality by network and clientBatchTelemetry partitioned by day and regionNever touches live state

6. High-level design

Media and signaling take different paths. Media goes from client to SFU over UDP when possible, through TURN when a firewall blocks UDP.

ComponentResponsibilityScales by
Meeting APIMeetings, join tokens, recordings, webhooksStateless instances
Signaling serviceWebSocket sessions, SDP exchange, layout, host actions, SFU assignmentConnections per node; stateless apart from sockets
SFUTerminate DTLS-SRTP, forward RTP, select layers, generate RTCP feedbackEgress bandwidth and packet rate (section 3.4)
TURN relayRelay media for clients that cannot reach the SFU directlyRelayed bandwidth (about 10% of sessions, Example)
Recorder sinkWrite forwarded packets of recorded meetings into segmentsRecorded meetings
Composer jobsDecode raw tracks and produce a playable file after the meetingBatch workers on spare capacity
SFU registryLoad and health of each SFU, heartbeatsSmall, per region

7. Detailed design

The deep dives in this section, each with options, choice and reason:

Deep diveOptions consideredChoiceReasonSection
TopologyMesh, MCU, SFUSFUConstant upload for senders, no server transcoding7.1
Quality adaptationSingle stream with server transcoding, simulcast, scalable video coding (SVC)Simulcast, SVC where every client supports itWorks with every WebRTC client today7.2, 7.3
Large and multi-region meetingsOne SFU per meeting, cascade of SFUsCascade by regionEach participant stays close to its SFU7.4
RecordingLive composite bot, raw track captureRaw tracks, composite after the meetingNo live decoding, cheaper at peak7.5

7.1 Topology: mesh, MCU or SFU

RFC 7667 describes the RTP topologies; the three relevant here are:

TopologyWhat the server doesSender uploadServer costFits
Mesh (point to point between every pair)Nothing in the media pathGrows with meeting sizeNoneTwo or three people
MCU (mixer)Decodes every stream, mixes one composite per layout, re-encodesOne streamHigh CPU per meeting, added latency of a decode and encodeLegacy room systems, very weak receivers
SFU (selective forwarding middlebox)Forwards packets and selects which stream each receiver getsOne stream per layerBandwidth and packet rate, little CPUInteractive meetings of any size

The SFU wins because it adds almost no latency (no decode), keeps CPU cost low and lets every receiver choose its own layout. Its weakness, that the sender must offer several qualities, is solved by simulcast.

7.2 Simulcast

Each sender encodes its camera at several resolutions at once and sends them as separate RTP streams, identified by a restriction identifier (rid) negotiated in SDP as RFC 8853 describes. In the W3C WebRTC API the sender sets sendEncodings on addTransceiver, one entry per layer, with rid and scaleResolutionDownBy.

pc.addTransceiver(cameraTrack, {
  direction: "sendonly",
  sendEncodings: [
    { rid: "l", scaleResolutionDownBy: 4, maxBitrate: 150000 },
    { rid: "m", scaleResolutionDownBy: 2, maxBitrate: 500000 },
    { rid: "h", scaleResolutionDownBy: 1, maxBitrate: 1500000 }
  ]
});

The SFU tells a sender to pause a layer nobody is receiving (for example the 720p layer when nobody has that participant in the large tile), which saves the sender's uplink and CPU. Screen share uses one high-resolution, low frame rate stream instead, because text must stay sharp.

7.3 Bandwidth estimation and layer selection

Two estimates drive adaptation:

  • Sender side: the sender's congestion controller estimates how much it can upload and sets the encoder bitrates. Browsers use delay-based and loss-based control (the Google Congestion Control approach, described in the expired draft-ietf-rmcat-gcc-02) driven by transport-wide feedback. RFC 8888 standardises an RTCP feedback format for congestion control.
  • Receiver side at the SFU: the SFU sends packets to each receiver and estimates that receiver's downlink from feedback about arrival times and loss. It then picks layers.

The layer selection loop runs per receiver every few hundred milliseconds:

  1. Start from the receiver's layout: one large tile, up to kk small tiles, the three loudest audio streams.
  2. Audio first: audio is never dropped for video.
  3. Give each small tile its lowest layer.
  4. Give the large tile the highest layer that still fits the estimate.
  5. If even the lowest layers do not fit, pause the small tiles and keep the large tile at its lowest layer; tell the client so it can show avatars.

Worked example with the ladder from 3.1 (Example):

Receiver estimateLarge tileSmall tilesAudioTotalResult
2.5 Mbps720p (1.5)3 x 180p (0.45)3 x 0.04 (0.12)2.07 MbpsFull layout
1.2 Mbps360p (0.5)3 x 180p (0.45)0.121.07 MbpsLarge tile steps down
0.5 Mbps180p (0.15)paused0.120.27 MbpsSmall tiles show avatars

A layer switch must happen on a key frame of the new layer, otherwise the receiver cannot decode. The SFU requests a key frame from the sender (RTCP picture loss indication) and switches when it arrives, and it rewrites sequence numbers and timestamps so the receiver sees one continuous stream. To avoid oscillation, step up only after the estimate has stayed above the next layer's bitrate plus 15% for a few seconds; step down at once.

Packet loss is handled per hop: the SFU retransmits lost packets to a receiver from its own short buffer (NACK), so a lossy receiver does not cause retransmissions from the sender to everyone. Audio relies on Opus forward error correction instead, because a retransmission arrives too late for speech.

7.4 Placement and cascading

  • Placement: the first participant in a region creates the meeting's presence on the least-loaded SFU of that region (by egress, not session count). Later participants in the same region join the same node, so one meeting stays on one SFU per region while it fits.
  • Cascade: when participants are in several regions, each region's SFU forwards to the other region's SFU only the layers that remote receivers need, once per layer and not once per receiver. A 40-person meeting split across two regions crosses the long-haul link with a few streams instead of dozens.
  • Large meetings: a meeting above the capacity of one SFU spreads its receivers over several SFUs in the same region connected as a tree. View-only attendees beyond about 1 000 move to the live streaming path, which trades seconds of latency for CDN scale.

7.5 Recording

Two options were compared for FR-06:

OptionHow it worksCost at peakQualityChosen
Live composite botA headless client joins, renders the layout, encodes one fileAbout 33 000 vCPU (3.5)What attendees sawNo
Raw track captureThe SFU copies forwarded packets of each track into segments; a composer decodes after the meetingStorage writes only during the meeting, batch CPU afterwardsCan render several layouts laterYes

Raw capture stores the 360p layer of each camera, the screen share and audio. Composition runs on batch capacity within the 30-minute target in FR-06. Participants are told that recording is on (visual indicator and an audible notice) before any packet is captured.

7.6 Security and end-to-end encryption

  • Transport: WebRTC requires DTLS-SRTP, so every media hop is encrypted. The SFU terminates SRTP, so in standard mode the operator can access media on the server (needed for recording and transcription).
  • E2EE mode: clients encrypt each encoded frame with SFrame (RFC 9605) before packetisation. Keys come from a group key agreement between clients, for example MLS (RFC 9420); the server only relays opaque handshake messages and sees epoch numbers. The SFU still routes packets and selects layers because RTP headers stay readable. Server recording, transcription and dial-in are disabled in this mode, and the UI shows a verification code participants can compare.
  • Access: join tokens are short-lived and bound to a role; a waiting room and meeting lock prevent uninvited joins; TURN credentials expire with the session.

7.7 How real systems do it

How real systems do it (paraphrased, not copied). Discord's engineering post "How Discord Handles Two and Half Million Concurrent Voice Users using WebRTC" (Jozsef Vass, 10 September 2018) explains that all calls are routed through Discord's own servers rather than peer to peer, because peer-to-peer cost rises with participants and routing through servers hides user IP addresses. A home-grown C++ SFU forwards audio and video and uses receiver reports to tell senders how much bandwidth they have. Native clients use a customised WebRTC media engine with a much smaller signaling exchange than full SDP, while browsers use the standard API. Signaling services assign a voice server from those registered in a service discovery system, and when a voice server fails its health check clients reconnect to a new one. The post reports more than 850 voice servers in 13 regions. Read the original in 12.3; this box keeps only the general idea.

8. Scalability and performance

ConcernApproachLimit before redesign
SFU egressPlace by egress load, pause unused layers, layout-driven subscriptionsExample: 6 Gbps per server at 60% NIC
Packet rateBatched sends, preallocated buffers, one forwarding thread per coreExample: About 1 million packets/s per server in load test
SignalingStateless WebSocket nodes, meeting state in a regional store[Connections per node]
Join storms at the top of the hourPre-warmed SFU capacity, join token issuance spread across API nodesExample: 7 400 joins/s
Large meetingsSFU tree inside a region, cascade between regions, view-only to streamingExample: 1 000 interactive receivers

Latency budget within one region (target p95 250 ms glass to glass):

StepBudget
Capture and encode40 ms
Sender to SFU network30 ms
SFU forwarding2 ms
SFU to receiver network30 ms
Jitter buffer60 ms
Decode and render30 ms
Headroom58 ms

9. Reliability, security and operations

9.1 Failure modes

ComponentFailureDetectionBlast radiusMitigationRTO
SFU nodeProcess crash or host lossMissed heartbeats, client ICE failureMeetings on that node in one regionClients reconnect through signaling to a new node; signaling replays track listExample: 5 s
SFU regionRegion outageRegistry empty, synthetic calls failParticipants in that regionSignaling assigns the next nearest region; higher latency acceptedExample: 30 s
Signaling nodeCrashWebSocket closeSessions on that node lose control messages, media continuesClient reconnects with session ID and resumesExample: 3 s
TURN relayOverload or outageAllocation failuresClients behind restrictive firewallsMultiple TURN pools, TLS on 443 fallbackExample: 60 s
NetworkBurst loss on a receiver linkReceiver loss and delay metricsOne receiverNACK from SFU buffer, layer step-down, Opus FECImmediate
Recorder sinkObject storage write errorsSegment upload failuresRecordings of affected meetingsLocal spool for 15 minutes, then alert host that recording is incompleteExample: 15 min
[Component][Failure][Signal][Scope][Mitigation][Time]

9.2 Security and abuse

ThreatControl
Uninvited joins ("meeting bombing")Join tokens, waiting room, lock, host removal, rate limits on join attempts
Media interceptionDTLS-SRTP on every hop; E2EE mode with SFrame for sensitive meetings
IP address exposure between participantsAll media through SFU or TURN, never peer to peer
TURN abuse as an open relayShort-lived credentials bound to a session, permissions only toward SFU addresses
Recording without noticeServer enforces visible and audible notice before capture starts
[Threat][Control]

9.3 Observability

SignalMetric or logAlert threshold
Media qualityFreeze rate, receiver loss, round-trip time per regionFreeze rate doubles vs. 7-day baseline
Join successJoins with first audio within 3 sBelow 99% for 10 min
SFU loadEgress Gbps, packets/s, CPU per nodeEgress above 70% of NIC
ReconnectsClient reconnects per 1 000 meeting-minutesDoubling vs. baseline
TURN shareSessions relayed through TURNAbove 20% (firewall or ICE regression)

9.4 Cost estimate

ItemUnit costQuantityMonthly cost
SFU servers[$/server-month]Example: About 870[$]
Egress bandwidth[$/GB]Example: 4.14 Tbps at peak, measure 95th percentile[$]
TURN relays[$/server-month][Count][$]
Recording storage[$/GB-month]Example: About 14 PB at 90-day retention[$]
Total[$]

10. Trade-offs and alternatives

DecisionOptionsChosenWhyWhat we give up
TopologyMesh; MCU; SFUSFU for all sizesConstant sender upload, no transcoding, per-receiver layoutsServer bandwidth bill; receivers decode several streams
AdaptationSimulcast; SVC; server transcodingSimulcast now, SVC where supportedWorks with all WebRTC clientsSender uploads about 43% more than its top layer alone
Two-person callsPeer to peer; SFUSFUOne code path, no IP exposureSmall added latency and server cost
RecordingLive composite; raw tracksRaw tracksNo live decoding at peakRecording ready minutes after the meeting, not instantly
E2EEAlways on; opt-in; noneOpt-inKeeps recording and transcription for most meetingsTwo modes to test and explain
What changes at 10x / 0.1x10x (20 million concurrent): about 41 Tbps egress, 6 900 servers at 10 Gbps or about 2 760 at 25 Gbps and 60%, so move to 25 or 100 Gbps NICs, push regions closer to users and negotiate peering. 0.1x (200 000 concurrent): about 69 SFU servers, one or two regions, and a managed TURN serviceReview at each doubling of peak participantsEgress and peering cost grow first[Note]
[Decision][Options][Chosen][Why][Cost]

11. Delivery plan and risks

11.1 Milestones

MilestoneScopeExit criterionTarget date
M1Signaling, single-region SFU, audio and one video layer25-person internal meetings for 2 weeksYYYY-MM-DD
M2Simulcast, layer selection, NACK and key frame handlingFreeze rate below target on emulated 1.2 Mbps linksYYYY-MM-DD
M3Multi-region cascade, TURN poolsCross-region p95 latency at or below 400 msYYYY-MM-DD
M4Raw track recording and composerRecordings ready within 30 min for 99% of meetingsYYYY-MM-DD
M5E2EE mode with SFrameExternal security review closedYYYY-MM-DD

11.2 Rollout and rollback

[Example: New SFU releases go to 1% of new meetings in one region, then 10%, then all, with automatic rollback when the freeze rate or reconnect rate rises by more than 20% against the previous release. Meetings already running stay on their node until they end; nodes are drained, never killed.]

11.3 Risks

IDRiskLikelihoodImpactMitigationOwner
R-01Example: Browser changes break simulcast negotiationMediumHighRun browser beta channels in the synthetic call suite[@name]
R-02Example: Egress cost exceeds planMediumHighLayout-driven subscriptions; pause unused layers; regional peering[@name]
R-03Example: E2EE key handling flawLowHighUse a reviewed MLS library; external audit before launch[@name]
[R-nn][Risk][L / M / H][L / M / H][Mitigation][@name]

12. Appendices

12.1 Open questions

IDQuestionOwnerDue
OQ-01Example: Which codecs do we require (VP8, VP9, AV1, H.264) for each client platform?[@name]YYYY-MM-DD
OQ-02Example: Do recordings need a separate legal notice per jurisdiction where participants join?[@name]YYYY-MM-DD
[OQ-nn][Question][@name]YYYY-MM-DD

12.2 Glossary

TermMeaning
SFUSelective forwarding unit: a server that forwards RTP packets and chooses which streams each receiver gets, without decoding
MCUMultipoint control unit: a server that decodes, mixes and re-encodes streams into one composite
SimulcastSending the same source at several qualities as separate streams
SVCScalable video coding: one stream with layers a server can drop
ICE, STUN, TURNNAT traversal: candidate gathering and checks, address discovery, media relay
PLI, NACKRTCP messages asking for a key frame and for retransmission of lost packets
SFrameFrame-level encryption for end-to-end protected media (RFC 9605)
[Term][Meaning]

12.3 References

ReferenceUse
W3C, "WebRTC: Real-Time Communication in Browsers", W3C Recommendation, 13 March 2025Browser API, sendEncodings, simulcast
RFC 3550 RTP: A Transport Protocol for Real-Time Applications (July 2003)RTP and RTCP
RFC 7667 RTP Topologies (November 2015)Mesh, mixer and selective forwarding middlebox, 7.1
RFC 8853 Using Simulcast in SDP and RTP Sessions (January 2021)7.2
RFC 8888 RTCP Feedback for Congestion Control (January 2021)7.3
draft-ietf-rmcat-gcc-02 Google Congestion Control (Internet-Draft of July 2016, expired January 2017)Background for 7.3
RFC 9429 JSEP (April 2024), RFC 8445 ICE, RFC 8656 TURNSignaling and NAT traversal
RFC 9605 SFrame (August 2024), RFC 9420 MLS (July 2023)7.6
Vass, "How Discord Handles Two and Half Million Concurrent Voice Users using WebRTC", Discord blog, 10 September 20187.7
Live Streaming System Design (system-design/design-live-streaming)View-only attendees beyond the interactive limit
Chat System Design (system-design/design-chat-system)In-meeting chat and presence
Notification Service Design (system-design/design-notification-service)Meeting reminders and recording-ready notices
Back-of-Envelope Estimation and Capacity Model (system-design/back-of-envelope-estimation)Method for section 3

Standard and licence note

Based on the W3C WebRTC Recommendation (13 March 2025) and the IETF RFCs cited in 12.3, which are public specifications. The Discord engineering post is paraphrased in 7.7 only; no text, figures or code were copied apart from the short reported counts attributed to it, and all other numbers here are illustrative examples. WebRTC specifications and browser support change; check the current W3C and IETF pages before implementing. Original text written for this collection. Template licence: MIT.

관련 템플릿