Failover profiles let olcRTC automatically move between signaling providers and transports when the active tunnel becomes unavailable. Instead of crashing or stalling, the built-in supervisor cycles through an ordered list of profiles — each with its own provider, room, and transport — until a working path is found or the maximum number of cycles is exhausted. Use failover when you need resilience across multiple providers (e.g. WbStream as the primary, Jitsi as the fallback), or when a single provider’s availability is unpredictable.Documentation Index
Fetch the complete documentation index at: https://mintlify.com/openlibrecommunity/olcrtc/llms.txt
Use this file to discover all available pages before exploring further.
How It Works
Apply top-level defaults
Fields defined at the top level of the YAML file (
crypto, net.dns, liveness, data, etc.) become shared defaults for every profile.Start the first profile
The supervisor applies the first entry in
profiles[], overriding only the fields specified inside that profile. The session starts.Detect failure
The liveness subsystem sends
CONTROL_PING / CONTROL_PONG over the encrypted control stream. When liveness.failures consecutive pongs are missed, the current session is considered dead.Try the next profile
The supervisor applies the next profile in the list and starts a new session. If the last profile fails, the cycle count increments and the supervisor wraps back to the first profile.
Failover-specific YAML Fields
Profile fields (profiles[])
Each entry in profiles can override any of the following fields from the shared defaults:
| Field | Description |
|---|---|
profiles[].name | Human-readable label for the profile (used in logs) |
profiles[].auth | Provider selection — overrides top-level auth |
profiles[].room | Room ID / channel — overrides top-level room |
profiles[].net | Transport and DNS — overrides top-level net |
profiles[].engine | Direct engine settings — overrides top-level engine |
profiles[].crypto | Encryption key — overrides top-level crypto |
profiles[].socks | SOCKS5 settings — overrides top-level socks |
profiles[].vp8 | VP8 transport tuning — overrides top-level vp8 |
profiles[].sei | SEI transport tuning — overrides top-level sei |
profiles[].video | Video transport tuning — overrides top-level video |
profiles[].liveness | Liveness tuning for this profile specifically |
profiles[].lifecycle | Lifecycle rotation for this profile specifically |
profiles[].traffic | Traffic shaping for this profile specifically |
Supervisor fields (failover)
| Field | Description |
|---|---|
failover.retry_delay | Pause between profile switch attempts, e.g. 2s |
failover.max_cycles | Maximum full passes over the profile list; 0 = infinite |
Full Failover Example
Supervisor Behaviour
Profile order is decisive. The supervisor always starts at profile index 0. When the active profile’s session fails (liveness timeout exhausted), the supervisor waitsretry_delay, then moves to the next profile by index. After the last profile fails, the full-cycle counter increments and the supervisor wraps back to profile 0.
Infinite cycling. Setting failover.max_cycles: 0 means the supervisor never stops on its own. It keeps rotating through profiles until the process is terminated or a profile establishes a stable session.
Liveness vs. profile switch. A single missed pong does not immediately trigger a profile switch. The supervisor only advances to the next profile after the liveness subsystem has exhausted its failures threshold and a reconnect attempt on the current profile also fails. Transient packet loss within the threshold is recovered on the same profile.
Lifecycle rotation with failover. When lifecycle.max_session_duration is set inside a profile (or as a shared default), a planned session rebuild at the end of that duration still re-uses the same profile — it is not a profile switch. The supervisor advances to the next profile only on failure.
The profile order must match on both server and client. The server and client independently run the same supervisor logic and must agree on which profile is active at any given time. If the profile lists differ between peers, the two sides will be in different provider/transport states and the session will not establish. Always deploy identical
profiles[] lists to both sides, changing only mode: srv vs mode: cnc.Liveness Interaction
Failover relies entirely on the liveness subsystem to detect dead tunnels — it does not use the WebRTC ICE or DTLS connection state. This means:- A
PeerConnectionthat is formallyconnectedbut routing no data will be detected byCONTROL_PING/CONTROL_PONGtimeouts. - Liveness checks run over the encrypted smux control stream, so only an end-to-end working path passes them.
- Adjust
liveness.failuresandliveness.timeoutper-profile if different providers have different latency characteristics.