We added live selling to a marketplace: a seller taps Start Live, buyers watch, ask questions in a chat, and buy without leaving the stream. The product brief was one sentence. The infrastructure behind it is where the actual decisions are.
"Just use WebRTC" is the answer you get when you ask about this, and it is roughly as useful as "just use TCP".
WebRTC is a media stack, not a service
WebRTC gives you encrypted real-time audio and video between two browsers, with echo cancellation, jitter buffers and congestion control already solved. That is a lot, and it is genuinely hard engineering you do not have to do.
What it does not give you is anything with a server in it. There is no signalling protocol in the spec — how two peers find each other and exchange their session descriptions is left entirely to you. There is no recording. There is no way to have a thousand viewers.
Those three gaps are the whole job.
Pick a topology before you pick a library
Everything downstream follows from this choice.
Mesh. Every participant connects directly to every other. For two people this is ideal — no server in the media path, minimum possible latency. It dies fast: each publisher uploads their stream once per viewer, so with N participants you are sending N-1 copies from a phone on mobile data. It stops being usable somewhere around four or five.
MCU (multipoint control unit). The server decodes everything, mixes it into a single composite stream and sends one stream out. Beautiful for clients — they receive one video — and brutally expensive, because the server is decoding and re-encoding everything in real time. It also flattens the layout: the server decided what the grid looks like.
SFU (selective forwarding unit). The server receives each publisher's stream and forwards it, without decoding. It is cheap in CPU, keeps latency low, and lets each subscriber choose what they receive. This is what every product you have used is built on, and for one-to-many live selling it is obviously right: one publisher, many subscribers, no mixing needed.
TURN is the line item people forget
Most WebRTC connections are established directly after a bit of NAT traversal with STUN. Most, not all.
Symmetric NAT, corporate firewalls that only allow 443, some mobile carrier networks — in those cases a direct path cannot be found and the media has to be relayed through a TURN server. Depending on your audience, somewhere in the region of one connection in ten needs it.
TURN relays actual media, so it costs real bandwidth, and it is the one piece you cannot make free. It is also the piece that turns "works for me" into "works for the customer behind a corporate proxy". Budget for it, run it on 443 over TLS so restrictive networks let it through, and test from a genuinely hostile network before you launch, not after.
Simulcast: publish three, subscribe to one
A seller on a good connection publishes 1080p. A buyer on a weak connection cannot receive it, and if the SFU forwards it anyway the stream stalls.
Simulcast solves this by having the publisher encode and send several qualities at once — say 1080p, 480p and 180p. The SFU then forwards whichever layer each subscriber's link can sustain, switching as conditions change, without ever decoding anything.
It costs the publisher upload bandwidth and CPU, which matters on a phone. The alternative — every subscriber getting the worst participant's experience — is worse. Turn it on.
The latency ladder
Choose by whether the audience talks back:
| Approach | Latency | Scales to | |---|---|---| | WebRTC (SFU) | 100–500 ms | thousands, with cost | | LL-HLS / LL-DASH | 2–5 s | millions, cheaply | | HLS / DASH | 6–30 s | millions, very cheaply |
Sub-second latency is expensive and you should only pay for it where it changes the product. A seller answering "does it come in blue?" out loud needs it — at six seconds of delay the conversation falls apart. A viewer watching a recorded launch does not.
The pragmatic architecture for live commerce is both: WebRTC for the seller and the handful of people who might join the call, HLS for the long tail of viewers, with the SFU's egress producing the HLS rendition. Interactive participants get real-time; passive viewers get cheap, reliable scale.
Where LiveKit fits
You can assemble this from parts — mediasoup, Janus, Pion — and you will spend months on the parts that are not the product: signalling, room state, reconnection, track subscription, adaptive layer selection, recording.
LiveKit is an open-source SFU that packages all of it, and it is the pragmatic default now:
- a room / participant / track model that matches how you would describe the feature out loud
- client SDKs for web, iOS, Android, React Native and Flutter — which mattered to us, because our app is Flutter and the alternatives had thin or community-maintained bindings
- simulcast and dynacast handled for you, including stopping layers nobody is subscribed to — a real bandwidth saving when the publisher is on a phone
- egress: record a room to storage, or push it to RTMP or HLS, without building a separate pipeline
- ingress: pull an RTMP or WHIP source in, so someone streaming from OBS lands in the same room as someone streaming from the app
- self-hostable, or their cloud, with the same SDKs
The egress and ingress pieces are what make the two-tier architecture above practical rather than a research project.
WHIP and WHEP
Worth knowing about: WHIP (ingest) and WHEP (playback) are small HTTP-based specifications that finally standardise WebRTC's missing signalling layer. One POST with an SDP offer, one answer back.
They make WebRTC boring in exactly the way RTMP has been boring for twenty years, and support is now broad enough to build on. If you are adding "go live from OBS" to a product, WHIP is the path of least resistance.
What I would tell myself before starting
- Decide mesh / SFU / MCU first. Everything else follows.
- Budget for TURN, on 443, over TLS. Test from a hostile network.
- Enable simulcast. One weak subscriber should not degrade everyone.
- Decide about recording early. Bolting it on later can force a topology change.
- Do not pay for sub-second latency where the audience is not talking back. Mix WebRTC and HLS.
- Instrument with
getStats()from day one. Without packet loss, jitter and bitrate per connection, every report becomes "it was laggy" and you have nothing to work with.
WebRTC solved the hard part — real-time media that survives a bad network. It deliberately left the servers, the scale and the recording to you. Knowing that before you start is the difference between a two-week feature and a two-quarter one.