Key points
- โWe shipped WebRTC video with STUN only, no TURN relay server, which means calls between users on restrictive networks โ roughly one in ten in our own connection logs โ can't establish a direct peer-to-peer connection.
- โRather than hide connection failures behind a generic error, we built explicit retry UX that tells users plainly when a call couldn't connect and what to try next, instead of a spinner that just times out silently.
- โWe chose WebRTC over an off-the-shelf video SDK specifically to keep session video peer-to-peer by default โ audio and video never route through our own servers unless a fallback is added.
Real-time video is a genuinely hard engineering problem, and most companies that do it well have entire teams dedicated to exactly that โ network engineers thinking about NAT traversal and relay infrastructure as their full-time job. We had neither the team nor the budget for that when we needed to ship video sessions for YouMindo's therapists and clients. We had to make a set of deliberate trade-offs instead, and be honest with users about what those trade-offs mean when a call doesn't connect.
The system that resulted works well for the large majority of sessions, connecting two devices directly with no noticeable delay and no server in between. It also fails in a specific, predictable way for a minority of connections, and early on we handled that failure badly โ with vague error messages at exactly the moment, right before a therapy session, when a confusing technical failure does the most damage to someone's day. We decided honesty about that failure mode mattered more than pretending it away with better-sounding error copy.
Why WebRTC over a video SDK
We considered several off-the-shelf video conferencing SDKs before deciding to build directly on WebRTC. The commercial options would have been faster to integrate, but nearly all of them route call traffic through the vendor's own servers by default, which meant therapy session video and audio passing through a third party's infrastructure. WebRTC, used correctly, lets two devices connect directly to each other. For a product handling therapy sessions, keeping that traffic peer-to-peer rather than relayed through anyone's servers was worth the extra engineering effort.
STUN, TURN, and the trade-off we made
WebRTC needs help establishing a direct connection between two devices that are both usually behind home routers and firewalls. A STUN server handles the common case โ it helps each device figure out its public address so a direct connection can be negotiated. A TURN server is the fallback for the harder case, relaying traffic between two devices when a direct connection genuinely can't be established. We shipped with STUN only. Running a TURN relay reliably and privately is a meaningfully larger infrastructure commitment, and we didn't have it ready at launch.
What happens without TURN
For most connections, STUN alone is enough โ the two devices find each other and connect directly, with no noticeable delay. For a minority of connections, usually where one or both people are on a restrictive corporate or mobile network, direct connection negotiation fails and there's no relay to fall back to. In our own connection logs, that's been roughly one call in ten. Those calls simply can't connect through the current system, and no amount of retrying the same way fixes it.
The mistake: early silent failures
Our first version handled a failed connection with a generic spinner that eventually timed out into a plain 'call failed' message, with no explanation of why or what to do next. Support tickets from confused, frustrated users โ often arriving late or upset for a session that then couldn't start โ made clear how bad that experience was. A generic failure message during a therapy session is close to the worst possible moment for vague error handling.
Designing the honest retry flow
We rebuilt the failure state to say, plainly, that a direct connection couldn't be established, and to offer concrete next steps: try a different network if one's available, such as switching from office WiFi to mobile data, or fall back to an audio-only call for that session. It's not a fix for the underlying limitation, but naming the problem accurately turned out to matter almost as much as solving it โ the support tickets we get now are calmer, even when the call still doesn't connect.
Why we didn't just add TURN immediately
Adding TURN support would fix the connection-failure cases. It also means running relay infrastructure that sees real-time call traffic pass through our servers for the calls that need it, and doing that reliably and securely at scale isn't a small addition โ it's close to a second infrastructure project. We chose to ship the peer-to-peer version honestly rather than delay launch further waiting for TURN to be ready, with a clear internal commitment to add it once we could do it properly rather than quickly.
What network diversity actually means for this problem
The failure case isn't random โ it clusters heavily around symmetric NAT configurations common on some corporate and carrier networks, which are specifically the kind of network topology STUN alone can't traverse. That's useful information operationally: we can often predict, in aggregate, which user populations are more likely to hit connection issues, which has shaped both our TURN rollout priority and the audio-only fallback we built as an interim option.
The audio-only fallback
When video can't connect, we offer an audio-only path over a separate, lighter-weight connection that succeeds far more often than video does, even on the same restrictive networks. It's not the same as a video session, and we say so. But a session that happens over audio is a meaningfully better outcome than a session that doesn't happen at all because the video connection never established โ and for now, it's the honest middle ground we have to offer.
Where TURN sits on the roadmap now
A TURN relay is in active development, scoped specifically to only route the calls that actually need it โ the roughly one-in-ten that STUN can't handle directly โ rather than relaying everything by default, to preserve the peer-to-peer privacy properties for the majority of sessions that don't need a relay at all. It's slower to build this way. We think it's the right way to build it for a product where session privacy is part of the product's basic promise.
A therapy session that can't connect is a genuinely bad experience, and we don't want to undersell how much that limitation costs some users right now. What we can control, until the infrastructure catches up, is whether the product is honest about what's happening and gives someone a real alternative in the moment โ an audio call instead of a dead spinner. That's a smaller promise than 'it always works.' It's the one we can actually keep today.
Marcus Webb is a former senior engineer at Headspace and Google. He co-founded YouMindo with a focus on building tools that support both clients and clinicians.