Router Guide

Deployment modes, quick start, and page map for Dynamo routing docs
View as Markdown

Overview

The Dynamo KV Router intelligently routes requests by evaluating their computational costs across different workers. It considers both decoding costs (from active blocks) and prefill costs (from newly computed blocks), using KV cache overlap to minimize redundant computation. Optimizing the KV Router is critical for achieving maximum throughput and minimum latency in distributed inference setups. This guide helps you get started with using the Dynamo router and points to the pages that cover routing concepts, configuration, disaggregated serving, and operations in more detail.

Deployment Modes

The Dynamo router can be deployed in several configurations. The table below shows every combination and when to use it:

ModeCommandRouting LogicKV EventsTopologyUse Case
Frontend + Round-Robinpython -m dynamo.frontend --router-mode round-robinCycles through workersNoneAggregatedSimplest baseline; no KV awareness
Frontend + Randompython -m dynamo.frontend --router-mode randomRandom worker selectionNoneAggregatedStateless load balancing
Frontend + KV (Aggregated)python -m dynamo.frontend --router-mode kvKV cache overlap + loadNATS Core / JetStream / ZMQ / ApproxAggregatedProduction single-pool serving with cache reuse
Frontend + KV (Disaggregated)python -m dynamo.frontend --router-mode kv with prefill + decode workersKV cache overlap + loadNATS Core / JetStream / ZMQ / ApproxDisaggregated (prefill + decode pools)Separate prefill/decode for large-scale serving
Frontend + Least-Loadedpython -m dynamo.frontend --router-mode least-loadedFewest active connectionsNoneAggregated or disaggregated fallbackSimple load-aware balancing without KV awareness
Frontend + Device-Aware Weightedpython -m dynamo.frontend --router-mode device-aware-weightedDevice-aware budget + least-loaded within selected device groupNoneAggregated or disaggregated fallbackHeterogeneous fleet balancing (CPU/non-CPU); degenerates to least-loaded when only one device class is present
Frontend + Directpython -m dynamo.frontend --router-mode directWorker ID from request hintsNoneAggregatedExternal orchestrator (e.g., EPP/GAIE) selects workers
Standalone Routerpython -m dynamo.routerKV cache overlap + loadNATS Core / JetStream / ZMQAnyRouting without the HTTP frontend (multi-tier, custom pipelines)

Routing Modes (--router-mode)

ModeValueHow Workers Are Selected
Round-Robinround-robin (default)Cycles through available workers in order
RandomrandomSelects a random worker for each request
KVkvEvaluates KV cache overlap and decode load per worker; picks lowest cost
Least-Loadedleast-loadedRoutes to the worker with fewest active connections; in disaggregated prefill paths it skips bootstrap optimization and falls back to synchronous prefill
Device-Aware Weighteddevice-aware-weightedPartitions workers into CPU and non-CPU groups, applies capability-normalized ratio budgeting using DYN_ENCODER_CUDA_TO_CPU_RATIO to decide which group receives the request, then selects the least-loaded worker within that group
DirectdirectReads the target worker_id from the request’s routing hints; no selection logic

Device-Aware Weighted Routing

device-aware-weighted is designed for heterogeneous fleets where workers of different compute capability, for example CPU embedding encoders alongside GPU embedding encoders, share the same endpoint.

Workers are split into CPU and non-CPU groups. The router compares a capability-normalized load across the two groups:

normalized_load = total_inflight(group) / (instance_count(group) x throughput_weight)

The throughput weight is 1 for CPU workers and DYN_ENCODER_CUDA_TO_CPU_RATIO for non-CPU workers. The next request is routed to the group with the lower normalized load, then to the least-loaded worker inside that group.

Use DYN_ENCODER_CUDA_TO_CPU_RATIO to approximate the throughput ratio of a non-CPU worker relative to one CPU worker. The default is 8.

When only one device class is present, the policy degenerates to standard least-loaded routing.

KV Event Transport Modes (within --router-mode kv)

When using KV routing, the router needs to know what each worker has cached. There are four ways to get this information:

Event ModeHow to EnableDescription
NATS Core (local indexer)Default (no extra flags)Workers maintain a local indexer; router queries workers on startup and receives events via NATS Core
JetStream (durable)--router-durable-kv-eventsEvents persisted in NATS JetStream; supports snapshots and durable consumers. Deprecated.
ZMQ--event-plane zmqWorkers publish via ZMQ PUB sockets; the standalone dynamo.indexer service aggregates events
Approximate (no events)--no-router-kv-eventsNo events consumed; router predicts cache state from its own routing decisions with TTL-based expiration

Aggregated vs. Disaggregated Topology

TopologyWorkersHow It Works
AggregatedSingle pool (prefill + decode in one process)All workers handle the full request lifecycle
DisaggregatedSeparate prefill and decode poolsFrontend routes to a prefill worker first, then to a decode worker; requires workers registered with ModelType.Prefill

Disaggregated mode is activated automatically when prefill workers register alongside decode workers. See Disaggregated Serving for details.

Frontend-Embedded vs. Standalone Router

DeploymentProcessMetrics PortUse Case
Frontend-embeddedpython -m dynamo.frontend --router-mode kvFrontend HTTP port (default 8000)Standard deployment; router runs inside the frontend process
Standalonepython -m dynamo.routerDYN_SYSTEM_PORT (if set)Multi-tier architectures, SGLang disagg prefill routing, custom pipelines

The standalone router does not include the HTTP frontend (no /v1/chat/completions endpoint). It exposes only the RouterRequestMetrics via the system status server. See the Standalone Router README.

Quick Start

Python / CLI Deployment

To launch the Dynamo frontend with the KV Router:

$python -m dynamo.frontend --router-mode kv --http-port 8000

This command:

  • Launches the Dynamo frontend service with KV routing enabled
  • Exposes the service on port 8000 (configurable)
  • Automatically handles all backend workers registered to the Dynamo endpoint

Backend workers register themselves using the register_model API, after which the KV Router automatically tracks worker state and makes routing decisions based on KV cache overlap.

CLI Arguments

ArgumentDefaultDescription
--router-mode kvround-robinEnable KV cache-aware routing
--router-temperature <float>0.0Controls routing randomness (0.0 = deterministic, higher = more random)
--kv-cache-block-size <size>Backend-specificKV cache block size (should match backend config)
--router-kv-events / --no-router-kv-events--router-kv-eventsEnable/disable real-time KV event tracking
--router-kv-overlap-score-weight <float>1.0Balance prefill vs decode optimization (higher = better TTFT)
--router-track-prefill-tokens / --no-router-track-prefill-tokens--router-track-prefill-tokensInclude prompt-side load in active worker load accounting
--router-prefill-load-model <none|aic>nonePrompt-side load model. aic decays only the oldest active prefill using an AIC-predicted duration
--router-queue-threshold <float>4.0Queue threshold fraction; enables priority scheduling via priority
--router-queue-policy <str>fcfsScheduling policy for the queue: fcfs (tail TTFT), wspt (avg TTFT), or lcfs (comparison-only reverse ordering)
--serve-indexerfalseServe the Dynamo-native remote indexer from this frontend/router on the worker component
--use-remote-indexerfalseQuery the worker component’s served remote indexer instead of maintaining a local overlap indexer

For all available options: python -m dynamo.frontend --help

For detailed configuration options and tuning parameters, see Configuration and Tuning.

AIC Prefill Load Model

The KV router can use AIC to estimate the expected duration of the selected worker’s prompt-side prefill work. When enabled, the router:

  • computes prefix = overlap_blocks * block_size for the chosen worker
  • computes effective_isl = input_tokens - prefix
  • stores one prompt-load hint for the admitted request
  • decays only the oldest active prefill request on each worker over time

This affects router-side prompt load accounting only. It does not change backend execution or decode-side accounting.

Enable it on the frontend like this:

$python -m dynamo.frontend \
> --router-mode kv \
> --router-prefill-load-model aic \
> --aic-backend vllm \
> --aic-system h200_sxm \
> --aic-model-path nvidia/Llama-3.1-8B-Instruct-FP8

The standalone router uses the same AIC flags:

$python -m dynamo.router \
> --endpoint dynamo.prefill.generate \
> --router-prefill-load-model aic \
> --aic-backend vllm \
> --aic-system h200_sxm \
> --aic-model-path nvidia/Llama-3.1-8B-Instruct-FP8

Required when --router-prefill-load-model=aic is enabled:

  • --router-mode kv on the frontend
  • --router-track-prefill-tokens
  • --aic-backend
  • --aic-system
  • --aic-model-path

Optional AIC knobs:

  • --aic-backend-version: pinned AIC database version; if omitted, Dynamo uses a backend-specific default
  • --aic-tp-size: tensor-parallel size for the modeled backend; defaults to 1

Kubernetes Deployment

To enable the KV Router in Kubernetes, add the DYN_ROUTER_MODE environment variable to your frontend service:

1apiVersion: nvidia.com/v1alpha1
2kind: DynamoGraphDeployment
3metadata:
4 name: my-deployment
5spec:
6 services:
7 Frontend:
8 dynamoNamespace: my-namespace
9 componentType: frontend
10 replicas: 1
11 envs:
12 - name: DYN_ROUTER_MODE
13 value: kv # Enable KV Smart Router

Key Points:

  • Set DYN_ROUTER_MODE=kv on the Frontend service only
  • Workers automatically report KV cache events to the router
  • No worker-side configuration changes needed

Environment Variables

All CLI arguments can be configured via environment variables using the DYN_ prefix:

CLI ArgumentEnvironment VariableDefault
--router-mode kvDYN_ROUTER_MODE=kvround-robin
--router-temperatureDYN_ROUTER_TEMPERATURE0.0
--kv-cache-block-sizeDYN_KV_CACHE_BLOCK_SIZEBackend-specific
--no-router-kv-eventsDYN_ROUTER_USE_KV_EVENTS=falsetrue
--router-kv-overlap-score-weightDYN_ROUTER_KV_OVERLAP_SCORE_WEIGHT1.0
--router-queue-policyDYN_ROUTER_QUEUE_POLICYfcfs
DYN_ENCODER_CUDA_TO_CPU_RATIO8Throughput ratio of a non-CPU worker relative to one CPU worker for device-aware-weighted routing

For complete K8s examples and advanced configuration, see K8s Examples and Configuration and Tuning. For A/B testing and advanced K8s setup, see the KV Router A/B Benchmarking Guide.

Standalone Router

You can also run the KV router as a standalone service (without the Dynamo frontend) for disaggregated serving (e.g., routing to prefill workers), multi-tier architectures, or any scenario requiring intelligent KV cache-aware routing decisions. See the Standalone Router component for more details.

More Router Docs