MoQT vs WebRTC: When to Use Which
By moqtap team
MoQT vs WebRTC: When to Use Which
The moment you say “low latency,” someone asks: why not just use WebRTC? It’s a fair question — WebRTC is the most battle-tested real-time media stack on the planet, it’s built into every browser, and it delivers latency MoQT doesn’t try to beat. If your problem is two people talking, WebRTC is almost always the answer.
But “low latency” hides two very different problems. One is conversation: a handful of participants, sub-200-millisecond round trips, everyone both sending and receiving. The other is distribution: one source (or a few), a live stream, and an audience that might be ten people or ten million. WebRTC was designed for the first. MoQT is designed for the second — and the MoQ working group’s charter names exactly that spread of use cases: “live streaming, gaming, and media conferencing.”
This post is about telling those two problems apart, because picking the wrong tool for your shape of problem is expensive in both directions.
WebRTC: built for conversation
WebRTC’s whole design serves interactive, bidirectional, few-party media:
- Transport: RTP/SRTP over UDP, with ICE/STUN/TURN for NAT traversal and DTLS for key exchange. Purpose-built for real time.
- Latency: routinely sub-200ms, often around 100ms — low enough that two people don’t talk over each other. Nothing in this comparison beats it for conversation.
- Reliability model: unreliable by default, with selective retransmission (NACK) and error concealment. A dropped frame is concealed, not stalled on.
Where it strains is fan-out. Native WebRTC is peer-to-peer: wonderful for 1:1, quadratic for a mesh. To reach a real audience you put a server in the middle — an SFU (Selective Forwarding Unit) that receives each publisher’s streams and forwards them to subscribers, or an MCU that mixes them. SFUs work, and they scale to meaningful numbers, but:
- Each SFU is stateful and media-aware, holding per-participant RTP state — heavier and pricier than an HTTP cache or a MoQT relay.
- Scaling past one SFU means cascading SFUs into a tree yourself; there’s no standard, cache-like fan-out layer you get for free.
- The stack is ossified around conferencing. Bending it toward broadcast-scale one-to-many distribution is possible but it’s swimming upstream against every default.
WebRTC is a superb conversation engine that you can press into distribution service. MoQT is a distribution engine from the first line of the spec.
MoQT: built for distribution at scale
MoQT keeps latency low but optimizes for the opposite axis — fanning one stream out to a large, changing audience:
- Transport: objects over QUIC (streams and datagrams), with QUIC’s no-head-of-line-blocking, 0-RTT, and connection migration.
- Latency: sub-second, tunable down toward the low hundreds of milliseconds. Generally not as low as WebRTC’s conversational floor — but in a completely different league from HLS.
- Fan-out: relay-based. One upstream subscription serves thousands of downstream subscribers through a relay tree, the same cache-like economics as a CDN. Relays cache immutable objects, so a late joiner starts milliseconds behind the live edge.
- One protocol across the spectrum. The same subscribe/object/priority model covers ingest and distribution, live and catch-up (via FETCH from relay cache).
The tradeoff is honest: MoQT gives up WebRTC’s absolute-lowest conversational latency in exchange for fan-out that scales like a CDN instead of like a fleet of SFUs.
The core difference is topology
Almost every practical difference falls out of one picture — how media gets from source to audience:
WebRTC (SFU) MoQT (relay tree)
Publisher Original Publisher │ │ ▼ ▼ ┌─────┐ per-participant ┌───────┐ caches objects │ SFU │ RTP state, media-aware │ Relay │ aggregates subs └─────┘ └───────┘ ╱ │ ╲ forwards to each ╱ │ ╲ ▼ ▼ ▼ subscriber ▼ ▼ ▼ ┌───────┐ sub sub sub sub sub └──►│ Relay │──► sub sub sub (cascade SFUs yourself └───────┘ to grow the tree) (relays chain like CDN edges)An SFU forwards live RTP with per-subscriber state and no natural caching layer. A relay caches immutable objects and aggregates many downstream subscriptions into one upstream request, so relays chain into a delivery tree the way CDN edges do — and a subscriber that joins late is served from cache instead of forcing a fresh upstream path. That single structural difference is why MoQT fans out cheaply and WebRTC makes you build the tree.
Side by side
| WebRTC | MoQT | |
|---|---|---|
| Designed for | interactive conversation | distribution at scale |
| Typical latency | sub-200ms | sub-second |
| Directionality | symmetric, bidirectional | publish/subscribe |
| Transport | RTP/SRTP over UDP | objects over QUIC |
| Scale unit | SFU (stateful, media-aware) | relay (caching, aggregating) |
| Fan-out to large audiences | cascade SFUs yourself | relay tree, CDN-like |
| Late joiner | fresh forwarding path | served from relay cache |
| Browser-native | yes | via WebTransport |
| Maturity | ubiquitous, battle-tested | pre-RFC (draft-19), maturing |
Which one — a decision framework
Reach for WebRTC when:
- Latency must be conversational (sub-200ms two-way): video calls, remote control, cloud gaming input, telepresence, anything where humans interrupt each other.
- The party count is small to moderate and everyone both sends and receives.
- You need it working in browsers today with a mature, standardized stack.
Reach for MoQT when:
- You’re distributing a live stream (a few sources, many consumers) and need sub-second, not sub-200ms.
- The audience is large and elastic — thousands to millions — and you want CDN-style fan-out without operating an SFU cascade.
- You want one protocol spanning ingest, live distribution, and catch-up, with priority and partial reliability built in.
- You’re coming down from HLS/DASH latency rather than up from a phone call — see MoQT vs HLS/DASH for that side.
Use both when: the interactive core and the broadcast audience are different populations. A common and powerful pattern is WebRTC for the interactive few, MoQT for the watching many — the presenters, players, or callers run WebRTC among themselves for the tightest possible loop, while the same media is republished into a MoQT relay tree for a large low-latency audience. You get WebRTC’s conversational latency where it’s needed and MoQT’s fan-out where it’s needed, instead of forcing one stack to do both jobs badly.
A note on honesty about maturity
WebRTC is a shipping standard with a decade of production hardening; MoQT is still pre-RFC at draft-18, with a relay ecosystem that’s actively maturing. If you need something bulletproof in production this quarter for a moderate audience, WebRTC’s maturity is a real and rational reason to choose it. MoQT’s argument is about where the shape of the problem is heading — large-scale live that has to be low-latency — and about not paying the SFU-cascade tax to get there. Match the tool to your problem’s shape first, and to your risk tolerance second.
Debugging across the boundary
If you run the hybrid pattern, the seam between WebRTC ingest and MoQT distribution is exactly where things break — and it’s a seam no single tool used to be able to see across. On the MoQT side, moqtap decodes the whole subscription and object flow, times subscribe-to-first-object and inter-object gaps, and shows the QUIC transport stats underneath — so when a viewer complains the stream is behind, you can tell whether the delay is in the relay tree, the network, or upstream of MoQT entirely. The debugging use case has the workflow.
Further reading
- W3C WebRTC specification — the browser real-time media API
- MoQ working group charter — MoQT’s low-latency + scale mandate
- What is MoQT? — the short version
- MoQT vs HLS/DASH — MoQT against the scale incumbent, the other half of the picture
- How MoQT relays work — the relay tree that replaces the SFU cascade
- How MoQT subscriptions work — the pub/sub model behind the fan-out
- MoQT implementation directory — the maturing relay and library ecosystem
Building the WebRTC-plus-MoQT hybrid and need to see the MoQT side clearly? moqtap Desktop and the WebTransport Inspector decode every subscription, object, and control message across drafts 07 through 19 — so the distribution half of your pipeline stops being a black box.