Why Group Video Calls Need an SFU (and How I Built One on mediasoup)
WebRTC's dirty secret: the peer-to-peer architecture everyone learns first stops working almost immediately.
In a mesh call, every participant uploads their stream to every other participant. With n people, that's n−1 outbound streams per person. At 4 participants you're pushing 3 simultaneous encodes up a residential connection; at 6, most laptops and uplinks are done.
The industry answer — and what I built with medisoup-sfu — is a Selective Forwarding Unit.
What an SFU actually does
An SFU is a media router, not a mixer:
- every participant uploads one stream to the server
- the server forwards (not decodes, not re-encodes) that stream to everyone who should receive it
Upload cost per client drops from O(n) to O(1). Server cost stays sane because forwarding packets is cheap — it's the transcoding (what an MCU does) that burns CPU. The SFU is the middle path: server-routed but codec-untouched.
The mediasoup model
mediasoup gives you the low-level Rust/C++ media engine with a Node.js API, and stays out of your signaling. The core objects map cleanly onto how you think about a call:
- Router — a room's media hub
- Producer — a participant's outgoing track (their camera, their mic, their screen)
- Consumer — one participant receiving one producer's track
- Transport — the DTLS/ICE plumbing each side connects through
Your job as the app developer is orchestration: create the router per room, negotiate transports, and wire up who consumes whom. That last part is your product — mute states, screen-share priority, who's visible in which layout — expressed as producer/consumer bookkeeping.
What I learned building it
- Signaling is yours. mediasoup deliberately ships none. WebSockets + your own message protocol; treat it as seriously as the media path, because every bug users see ("stuck joining…") lives there.
- Room state is a distributed-systems problem. Participants disconnect mid-negotiation constantly. Model the room as state that must survive any participant vanishing at any step.
- Selective forwarding is a feature surface. Once the server decides who gets which stream, things like "only forward the active speaker at full quality" stop being hacks and start being one line of routing policy.
Real-time media is the most fun distributed-systems playground I know: hard latency budgets, humans noticing every failure, and no batch job to hide behind.
// RELATED_TRANSMISSIONS
- MyMQ (Redis-based queue) & Redis-compatible KV in GoBuilt MyMQ: a Redis-inspired message queue in TypeScript, and a Redis-compatible key-value store in Go to learn systems programming and concurrency.
- PHANTOM: I Built a Benchmark Where an RL Attacker Gaslights an LLM DefenderMost cybersecurity benchmarks test what an agent knows. PHANTOM tests whether it can still think when a co-evolving adversary is lying to it in real time.
- Veris: Building a Camera That Cannot LieA Raspberry Pi camera with a hardware-derived ed25519 identity, on-chain signature verification on Solana, and Filecoin storage. Deepfakes die at capture time.