---
title: router
---

<div class="python-reference">
<a id="fastvideo.entrypoints.streaming.router-classes"></a>
<a id="fastvideo.entrypoints.streaming.router-functions"></a>
<a id="fastvideo.entrypoints.streaming.router.ReplicaRegistry-functions"></a>
<a id="fastvideo.entrypoints.streaming.router"></a>
<p>Multi-replica load balancer + WebSocket proxy for the streaming server.</p>
<p>Sits in front of one-or-more streaming-server replicas and forwards
WebSocket sessions to a healthy primary, with failover to secondaries.
Kept in-repo under <code>fastvideo/entrypoints/streaming/router/</code> per the
PR plan's default; the alternative (separate package) is an open
question deferred to review.</p>
<h2 id="fastvideo.entrypoints.streaming.router.Replica"><code>fastvideo.entrypoints.streaming.router.Replica</code></h2>
<pre class="doc-signature"><code>Replica(endpoint: ReplicaEndpoint, health: ReplicaHealth = ReplicaHealth())</code></pre>


<h2 id="fastvideo.entrypoints.streaming.router.ReplicaHealth"><code>fastvideo.entrypoints.streaming.router.ReplicaHealth</code></h2>
<pre class="doc-signature"><code>ReplicaHealth(status: ReplicaStatus = ReplicaStatus.UNKNOWN, last_ok_at: float | None = None, last_failure_at: float | None = None, consecutive_failures: int = 0, consecutive_successes: int = 0, last_latency_ms: float | None = None)</code></pre>


<h2 id="fastvideo.entrypoints.streaming.router.ReplicaRegistry"><code>fastvideo.entrypoints.streaming.router.ReplicaRegistry</code></h2>
<pre class="doc-signature"><code>ReplicaRegistry(replicas: list&#91;ReplicaEndpoint&#93;)</code></pre>
<p>Stateful map of replica URL → :class:<code>Replica</code>.</p>
<p>Selection favors primary replicas when healthy; otherwise the first
healthy non-primary is returned. When none are healthy, the
registry returns <code>None</code> so the router can reject incoming
sessions with <code>gpu_unavailable</code>.</p>

<h3 id="fastvideo.entrypoints.streaming.router.ReplicaRegistry.all"><code>fastvideo.entrypoints.streaming.router.ReplicaRegistry.all</code></h3>
<pre class="doc-signature"><code>all() -&gt; list&#91;Replica&#93;</code></pre>

<h3 id="fastvideo.entrypoints.streaming.router.ReplicaRegistry.get"><code>fastvideo.entrypoints.streaming.router.ReplicaRegistry.get</code></h3>
<pre class="doc-signature"><code>get(url: str) -&gt; Replica | None</code></pre>

<h3 id="fastvideo.entrypoints.streaming.router.ReplicaRegistry.primaries"><code>fastvideo.entrypoints.streaming.router.ReplicaRegistry.primaries</code></h3>
<pre class="doc-signature"><code>primaries() -&gt; list&#91;Replica&#93;</code></pre>

<h3 id="fastvideo.entrypoints.streaming.router.ReplicaRegistry.select"><code>fastvideo.entrypoints.streaming.router.ReplicaRegistry.select</code></h3>
<pre class="doc-signature"><code>select() -&gt; Replica | None</code></pre>
<p>Pick the best healthy replica.</p>
<p>Priority order:</p>
<ol>
<li>The first healthy primary (insertion order).</li>
<li>The first healthy non-primary (insertion order).</li>
<li><code>None</code> when nothing is healthy.</li>
</ol>
<p>This MVP picks the first match within each tier; it does NOT
load-balance across multiple healthy replicas of the same tier.
Round-robin and weighted distribution are deferred until a real
N-way active deployment exists.</p>
<h3 id="fastvideo.entrypoints.streaming.router.ReplicaRegistry.record_success"><code>fastvideo.entrypoints.streaming.router.ReplicaRegistry.record_success</code></h3>
<pre class="doc-signature"><code>record_success(replica: Replica, *, recovery_threshold: int, latency_ms: float) -&gt; None</code></pre>

<h3 id="fastvideo.entrypoints.streaming.router.ReplicaRegistry.record_failure"><code>fastvideo.entrypoints.streaming.router.ReplicaRegistry.record_failure</code></h3>
<pre class="doc-signature"><code>record_failure(replica: Replica, *, failure_threshold: int, reason: str) -&gt; None</code></pre>

<h2 id="fastvideo.entrypoints.streaming.router.ReplicaStatus"><code>fastvideo.entrypoints.streaming.router.ReplicaStatus</code></h2>
<pre class="doc-signature"><code>ReplicaStatus()</code></pre>

<h2 id="fastvideo.entrypoints.streaming.router.RouterConfig"><code>fastvideo.entrypoints.streaming.router.RouterConfig</code></h2>
<pre class="doc-signature"><code>RouterConfig(host: str = &#x27;0.0.0.0&#x27;, port: int = 9000, replicas: list&#91;ReplicaEndpoint&#93; = list(), health_check_path: str = &#x27;/health&#x27;, health_check_interval_seconds: float = 5.0, health_check_timeout_seconds: float = 2.0, failure_threshold: int = 3, recovery_threshold: int = 2)</code></pre>
<p>Typed router config loaded from a YAML file.</p>
<p>Example::</p>
<pre><code>router:
  host: 0.0.0.0
  port: 9000
  replicas:
    - url: http://streamer-a:8000
      primary: true
    - url: http://streamer-b:8000
  health_check:
    path: /health
    interval_seconds: 5
    failure_threshold: 3
</code></pre>
<p>Validation runs in <code>__post_init__</code>: empty replicas, non-positive
intervals/timeouts, thresholds &lt; 1, non-http(s) URLs, and more than
one primary all raise <code>ValueError</code> so misconfigurations surface at
load time rather than as confusing runtime failures.</p>

<h2 id="fastvideo.entrypoints.streaming.router.build_router_app"><code>fastvideo.entrypoints.streaming.router.build_router_app</code></h2>
<pre class="doc-signature"><code>build_router_app(config: RouterConfig, *, registry: ReplicaRegistry | None = None) -&gt; FastAPI</code></pre>
<p>Build the router FastAPI app.</p>
<p><code>registry</code> can be injected for tests; defaults to one built from
<code>config.replicas</code>.</p>
<h2 id="fastvideo.entrypoints.streaming.router.run_router"><code>fastvideo.entrypoints.streaming.router.run_router</code></h2>
<pre class="doc-signature"><code>run_router(config: RouterConfig) -&gt; None</code></pre>

</div>

<h2>Submodules</h2>
<ul>
<li><a href="/FastVideo/api/fastvideo/entrypoints/streaming/router/config">config</a></li>
<li><a href="/FastVideo/api/fastvideo/entrypoints/streaming/router/main">main</a></li>
<li><a href="/FastVideo/api/fastvideo/entrypoints/streaming/router/registry">registry</a></li>
</ul>
