| Field | Value |
|---|---|
| Repo | ai-dynamo/dynamo |
| Primary language | Rust (54.3%), Python (30.4%), Go (13.1%) |
| LOC | ~29.2M total (Rust 15.9M, Python 8.9M, Go 3.8M) |
| License | Apache-2.0 |
| Stars | 7,082 |
| Maintainer / Sponsor | NVIDIA Inc. |
| Stable version | v1.1.1 (2026-05-09) |
| Pre-release | v1.2.0-deepseek-v4-dev.3 |
Trilingual project: Rust for the performance-critical runtime, router, and KV block manager; Python for user-facing frontend, planner, and backend integrations; Go for the Kubernetes operator.
One-line pitch: The orchestration layer above inference engines — turns SGLang, TRT-LLM, or vLLM into a coordinated multi-node inference system with disaggregated serving, KV-aware routing, multi-tier KV caching, and SLA-driven autoscaling.
Problem: Single-engine inference servers hit a wall at datacenter scale. Three specific gaps:
核心技术壁垒: The KV-aware radix-tree router (dynamo-kv-router). It maintains a concurrent, compressed radix tree of all active KV cache prefixes across the cluster. Routing decisions factor in both prefix overlap score and worker load, solving a joint optimization that simpler heuristics (hash-based affinity, random) miss. The concurrent tree implementation uses lock-free reads with fine-grained locking for writes, enabling microsecond-latency routing decisions at hundreds of thousands of QPS — the single hardest component to replicate because it couples a custom concurrent data structure with domain-specific scheduling policies (FCFS, WSPT).
Module roles:
| Module | Location | Purpose |
|---|---|---|
dynamo-runtime | lib/runtime/ | Tokio executor management, cancellation tokens, service discovery, 3-phase shutdown |
dynamo-llm | lib/llm/ | HTTP frontend, engine abstraction, model cards, telemetry |
dynamo-kv-router | lib/kv-router/ | Concurrent radix tree, scheduling policies, prefix overlap scoring |
kvbm-engine | lib/kvbm-engine/ | 4-tier KV block offload with CUDA copy kernels |
dynamo-protocols | lib/protocols/ | OpenAI / Anthropic / Responses API type definitions |
components/ | components/src/dynamo/ | Python frontend, router glue, planner, profiler, backend integrations |
deploy/operator/ | deploy/operator/ | Go-based K8s operator for topology-aware gang scheduling |
Python public API — import dynamo:
dynamo.llm: EntrypointArgs, EngineType, KvRouterConfig, RouterConfig, RouterMode, make_engine, run_inputdynamo.runtime: DistributedRuntimedynamo.frontend: main entry point (python -m dynamo.frontend)dynamo.vllm, dynamo.sglang, dynamo.trtllm: backend-specific workersCLI entry points (from pyproject.toml scripts and modules):
| Entry point | What it does |
|---|---|
python -m dynamo.frontend | Starts HTTP/gRPC server with chosen router mode |
python -m dynamo.vllm | Starts vLLM backend worker |
python -m dynamo.sglang | Starts SGLang backend worker |
python -m dynamo.trtllm | Starts TRT-LLM backend worker |
dynamo-kv-indexer | Standalone KV indexer (Rust binary via maturin) |
Top 10 configuration knobs:
| Flag / Env | Default | Effect |
|---|---|---|
--router-mode | round-robin | Routing strategy: kv, random, direct, power-of-two, least-loaded, device-aware-weighted, round-robin |
--http-port | 8000 | Frontend listen port |
--discovery-backend | etcd | Service discovery: etcd, file (local dev), K8s-native |
--kv-cache-block-size | engine default | KV cache block granularity in tokens |
--migration-limit | none | Max concurrent in-flight request migrations |
--interactive | false | Text-mode interactive REPL instead of HTTP |
--kserve-grpc-server | false | Start gRPC instead of HTTP |
SLA YAML (ttft, itl) | none | Planner targets for time-to-first-token and inter-token latency |
autoApply (K8s CR) | false | Let AIConfigurator auto-deploy optimal config |
| Backend-specific flags | varies | Passed through to vLLM / SGLang / TRT-LLM (TP, PP, batch size, etc.) |
Extension points:
examples/custom_backend/ Python templateSchedulingPolicy trait (lib/kv-router/src/scheduling/policy.rs)WorkerSelector traitRuntime (lib/runtime/src/runtime.rs) #
pub struct Runtime {
id: Arc<String>,
primary: RuntimeType, // tokio Runtime for async I/O
secondary: RuntimeType, // tokio Runtime for compute-heavy tasks
cancellation_token: CancellationToken,
endpoint_shutdown_token: CancellationToken,
graceful_shutdown_tracker: Arc<GracefulShutdownTracker>,
compute_pool: Option<Arc<compute::ComputePool>>,
block_in_place_permits: Option<Arc<tokio::sync::Semaphore>>,
}
from_settings(). Owned by the main function. Destroyed on shutdown() (3-phase protocol).Arc; the struct itself is Send + Sync. The dual-runtime design (primary for I/O, secondary for CPU-bound work) avoids executor starvation.block_in_place_permits gates tokio::task::block_in_place calls to prevent thread pool exhaustion.ConcurrentRadixTree / ConcurrentRadixTreeCompressed (lib/kv-router/src/indexer/) #The core routing data structure. Maps token-sequence prefixes to worker IDs with overlap scores.
WorkerId, block hashes, and child pointers. At scale (millions of cached sequences), memory is dominated by prefix edges.lib/kvbm-engine/src/lib.rs) #
pub struct G1; // GPU/HBM
pub struct G2; // CPU/DRAM (RDMA staging)
pub struct G3; // NVMe/SSD
pub struct G4; // S3/MinIO
Zero-sized type markers used as generic parameters in the offload pipeline: Offloader moves blocks from GPU to CPU, Offloader from CPU to SSD, etc. Block identity is tracked by BlockId (u64 hash of sequence content), and logical-to-physical mapping by LogicalLayoutHandle.
EntrypointArgs / RouterConfig (Python side) #
e = EntrypointArgs(EngineType.Dynamic, **kwargs)
router_config = RouterConfig(router_mode, kv_router_config, **kwargs)
Dataclass-like configuration carriers. EngineType.Dynamic means the frontend discovers backends at runtime via service discovery, as opposed to EngineType.Static for single-engine mode.
Request hot path: HTTP request → response tokens.
Latency budget (estimated from architecture, not profiled):
| Hop | Estimated | Notes |
|---|---|---|
| HTTP parse + tokenize | ~0.5 ms | Tokenizer is Rust (fastokens) via PyO3 |
| Router scheduling | ~0.01-0.1 ms | Radix tree lookup + policy evaluation; designed for <100 µs |
| NATS request forward | ~0.1-0.5 ms | If using event plane; direct TCP is lower |
| Prefill | 10-1000+ ms | Dominates TTFT; varies with prompt length |
| Decode per token | 5-50 ms | Varies with model size and batch |
The README claims KV-aware routing yields 2x TTFT improvement. This is plausible: if 80% of a prompt's prefix is already cached on a worker, prefill cost drops from $O(n)$ to $O(0.2n)$, which is a 5x reduction in prefill time, partially offset by slightly higher load on the cache-hot worker.
Mismatch with docs: The README says "7x higher throughput per GPU" for DeepSeek R1 on GB200 NVL72, but this combines disaggregated serving + KV routing + NVLink topology awareness — the 7x is a system-level number, not attributable to any single component.
Concurrency model: hybrid async + threaded.
| Layer | Model | Details |
|---|---|---|
| Rust runtime | tokio async | Dual-runtime: primary for I/O, secondary for CPU-bound tasks. block_in_place gated by semaphore to prevent pool saturation. |
| KV router | Lock-free reads + fine-grained write locks | Radix tree uses epoch-based memory reclamation. ZMQ-based inter-node sync for the KV indexer. |
| Python frontend | asyncio (single-threaded event loop) | Bridges to Rust via PyO3 asyncio.Future. No GIL contention on hot path since compute is in Rust. |
| Backend workers | Per-engine | vLLM/SGLang run their own async loops. TRT-LLM uses thread-based execution. |
| K8s operator (Go) | goroutines | Standard controller-runtime concurrency. |
Shutdown protocol (3-phase):
endpoint_shutdown_token — stop accepting new requestsGracefulShutdownTracker::wait_for_completion() — drain in-flight requestscancellation_token — disconnect NATS/etcdThis is significantly more sophisticated than a simple CancellationToken::cancel(). The tracker uses an atomic counter; each graceful endpoint increments on entry, decrements on exit. Phase 2 blocks until the counter hits zero.
Memory management:
Arc reference counting everywhere. No raw pointers in user-facing code. KVBM uses CUDA cudaMallocHost for pinned CPU buffers.Headline benchmarks (from README, externally validated):
| Metric | Value | Config |
|---|---|---|
| Throughput gain | 7x per GPU | DeepSeek R1, GB200 NVL72, Dynamo vs standalone B200 (InferenceX) |
| Throughput gain | 750x | DeepSeek-R1, GB300 NVL72 (InferenceXv2) |
| TTFT improvement | 2x | KV-aware routing, Qwen3-Coder 480B (Baseten) |
| SLA breach reduction | 80% fewer | Planner autoscaling at 5% lower TCO (Alibaba APSARA 2025) |
| Cold-start speedup | 7x | ModelExpress weight streaming, DeepSeek-V3 on H200 |
Scaling dimensions:
Where the time goes (architectural analysis):
Dependency health:
tokio = "=1.48.0", axum = "=0.8.4", hyper = "=1.7.0". Transitive deps pinned via [patch.crates-io] to specific git commits. This prevents supply-chain surprises but creates upgrade debt.velo 0.1.0: Internal/companion library for KVBM peer communication. Not on crates.io — likely an NVIDIA internal dependency. Bus factor = 1 library.Testing:
tests/ directory; E2E tests for each backend.benchmarks/ covers LLM latency/throughput, router microbenchmarks, frontend load testing, and multimodal.lib/mocker/ module enables testing without GPUs via a mock inference engine.Known warts:
v1.2.0-deepseek-v4-dev.3 suggest model-specific forks that may diverge from mainline, creating merge debt.| Metric | Value |
|---|---|
| Stars | 7,082 |
| Contributors (v1.1.0) | 113 (over 896 PRs) |
| Release cadence | ~biweekly (v1.0.2 → v1.1.0 → v1.1.1 in 16 days) |
| Governance | Corporate-backed (NVIDIA) |
| License | Apache-2.0 |
The 113-contributor count for a single release suggests significant internal NVIDIA engineering investment. The Apache-2.0 license enables commercial adoption without reciprocal obligations.
| Dimension | Dynamo | Ray Serve / vLLM standalone | Triton Inference Server |
|---|---|---|---|
| Multi-engine support | SGLang + TRT-LLM + vLLM | vLLM only (or Ray Serve generic) | Multi-framework but no LLM-specific routing |
| Disaggregated P/D | Native with independent scaling | vLLM 0.8+ has basic P/D | Not supported |
| KV-aware routing | Radix tree + overlap scoring | vLLM prefix caching is intra-node only | None |
| Multi-tier KV cache | 4-tier (GPU→CPU→SSD→S3) | GPU-only KV cache | N/A |
| Autoscaling | SLA-driven Planner + AIConfigurator | Ray autoscaler (generic) | Triton model analyzer (static) |
| K8s integration | Custom operator (Grove) + Inference Gateway | KubeRay | Triton Kubernetes integration |
| Language | Rust + Python + Go | Python | C++ + Python |
| Cold-start | 7x faster via ModelExpress/NIXL | Standard model loading | Standard model loading |
| Maturity | v1.1 (2026, ~1 yr old) | vLLM ~2 yrs, Ray ~5 yrs | ~6 yrs, battle-tested |
Winner per dimension: Dynamo leads on LLM-specific features (disaggregation, KV routing, multi-tier cache). Triton leads on maturity and non-LLM workloads. Ray Serve leads on ecosystem breadth.
When to adopt:
When NOT to adopt:
关键实现细节 (easy-to-miss tricks):
primary/secondary runtime split prevents CPU-heavy tokenization or scheduling from starving I/O handlers. The block_in_place_permits semaphore is the pressure valve — without it, block_in_place calls can consume all runtime threads.dynamo-kv-indexer binary) means a router crash doesn't lose the prefix tree, and the indexer can be independently scaled / monitored. Recovery from node failure uses a peer /dump endpoint to bootstrap the tree from surviving nodes, plus inline ZMQ gap detection for missed events.| Component | Location |
|---|---|
| Runtime 3-phase shutdown | lib/runtime/src/runtime.rs — Runtime::shutdown() |
| KV router radix tree | lib/kv-router/src/indexer/ — ConcurrentRadixTree, ConcurrentRadixTreeCompressed |
| Scheduling policies | lib/kv-router/src/scheduling/policy.rs — FcfsPolicy, WsptPolicy |
| KVBM 4-tier structs | lib/kvbm-engine/src/lib.rs — G1, G2, G3, G4 |
| Frontend entry point | components/src/dynamo/frontend/main.py — async_main() |
| Python bindings | lib/bindings/python/ — PyO3/maturin |
| K8s operator | deploy/operator/ — Go controller-runtime |
| CUDA copy kernels | lib/kvbm-kernels/ |