---
title: config
---

<div class="python-reference">
<a id="fastvideo.entrypoints.streaming.router.config-classes"></a>
<a id="fastvideo.entrypoints.streaming.router.config.ReplicaEndpoint-attributes"></a>
<a id="fastvideo.entrypoints.streaming.router.config"></a>
<p>Typed router configuration.</p>
<h2 id="fastvideo.entrypoints.streaming.router.config.ReplicaEndpoint"><code>fastvideo.entrypoints.streaming.router.config.ReplicaEndpoint</code></h2>
<pre class="doc-signature"><code>ReplicaEndpoint(url: str, name: str | None = None, primary: bool = False, weight: float = 1.0)</code></pre>
<p>One backend replica the router can route to.</p>

<details><summary>Source</summary><pre><code>@dataclass
class ReplicaEndpoint:
    &quot;&quot;&quot;One backend replica the router can route to.&quot;&quot;&quot;

    url: str
    &quot;&quot;&quot;HTTP base URL, e.g. ``http://host:8000``. WebSocket URL is
    derived automatically by replacing the scheme.&quot;&quot;&quot;
    name: str | None = None
    primary: bool = False
    &quot;&quot;&quot;``True`` = prefer this replica over others in steady state.&quot;&quot;&quot;
    weight: float = 1.0</code></pre></details>
<h3 id="fastvideo.entrypoints.streaming.router.config.ReplicaEndpoint.url"><code>fastvideo.entrypoints.streaming.router.config.ReplicaEndpoint.url</code></h3>
<pre class="doc-signature"><code>url: str</code></pre>
<p>HTTP base URL, e.g. <code>http://host:8000</code>. WebSocket URL is
derived automatically by replacing the scheme.</p>
<details><summary>Source</summary><pre><code>url: str</code></pre></details>
<h3 id="fastvideo.entrypoints.streaming.router.config.ReplicaEndpoint.primary"><code>fastvideo.entrypoints.streaming.router.config.ReplicaEndpoint.primary</code></h3>
<pre class="doc-signature"><code>primary: bool = False</code></pre>
<p><code>True</code> = prefer this replica over others in steady state.</p>
<details><summary>Source</summary><pre><code>primary: bool = False</code></pre></details>
<h2 id="fastvideo.entrypoints.streaming.router.config.RouterConfig"><code>fastvideo.entrypoints.streaming.router.config.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>

<details><summary>Source</summary><pre><code>@dataclass
class RouterConfig:
    &quot;&quot;&quot;Typed router config loaded from a YAML file.

    Example::

        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

    Validation runs in ``__post_init__``: empty replicas, non-positive
    intervals/timeouts, thresholds &lt; 1, non-http(s) URLs, and more than
    one primary all raise ``ValueError`` so misconfigurations surface at
    load time rather than as confusing runtime failures.
    &quot;&quot;&quot;

    host: str = &quot;0.0.0.0&quot;
    port: int = 9000
    replicas: list&#91;ReplicaEndpoint&#93; = field(default_factory=list)
    health_check_path: str = &quot;/health&quot;
    health_check_interval_seconds: float = 5.0
    health_check_timeout_seconds: float = 2.0
    failure_threshold: int = 3
    recovery_threshold: int = 2

    def __post_init__(self) -&gt; None:
        if not self.replicas:
            raise ValueError(&quot;RouterConfig.replicas must list at least one replica&quot;)
        if self.health_check_interval_seconds &lt;= 0:
            raise ValueError(f&quot;health_check_interval_seconds must be &gt; 0, got &#123;self.health_check_interval_seconds&#125;&quot;)
        if self.health_check_timeout_seconds &lt;= 0:
            raise ValueError(f&quot;health_check_timeout_seconds must be &gt; 0, got &#123;self.health_check_timeout_seconds&#125;&quot;)
        if self.failure_threshold &lt; 1:
            raise ValueError(f&quot;failure_threshold must be &gt;= 1, got &#123;self.failure_threshold&#125;&quot;)
        if self.recovery_threshold &lt; 1:
            raise ValueError(f&quot;recovery_threshold must be &gt;= 1, got &#123;self.recovery_threshold&#125;&quot;)
        seen_urls: set&#91;str&#93; = set()
        for replica in self.replicas:
            if not replica.url.startswith((&quot;http://&quot;, &quot;https://&quot;)):
                raise ValueError(f&quot;ReplicaEndpoint.url must start with http:// or https://, got &#123;replica.url!r&#125;&quot;)
            parsed = urlparse(replica.url)
            if parsed.path not in (&quot;&quot;, &quot;/&quot;):
                raise ValueError(f&quot;ReplicaEndpoint.url must be a base host&#91;:port&#93; URL without a path; &quot;
                                 f&quot;got &#123;replica.url!r&#125; with path &#123;parsed.path!r&#125;. The router appends &quot;
                                 &quot;`/health` and `/v1/stream` itself.&quot;)
            if parsed.query or parsed.fragment:
                raise ValueError(f&quot;ReplicaEndpoint.url must not include query/fragment; got &#123;replica.url!r&#125;&quot;)
            if replica.url in seen_urls:
                raise ValueError(f&quot;Duplicate ReplicaEndpoint.url &#123;replica.url!r&#125;; &quot;
                                 &quot;router selection keys by URL so duplicates would silently collapse&quot;)
            seen_urls.add(replica.url)
        primaries = sum(1 for r in self.replicas if r.primary)
        if primaries &gt; 1:
            raise ValueError(f&quot;RouterConfig allows at most one primary replica; got &#123;primaries&#125;. &quot;
                             &quot;Multi-primary load distribution is deferred — promote one replica to &quot;
                             &quot;primary and treat the rest as secondaries.&quot;)</code></pre></details>
</div>
