Repository navigation
fix(router): make the per-class decode wait limit correct for disaggregated serving - #108
Draft
ishandhanani wants to merge 225 commits into
Draft
ishandhanani wants to merge 225 commits into
ishandhanani wants to merge 225 commits into
Conversation
Signed-off-by: Andrew Paprotsky <apaprotskyi@nvidia.com> Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
…17006) Signed-off-by: xianlubird <xianlubird@gmail.com>
ishandhanani
had a problem deploying
to
external_collaborator
October 29, 2026 09:54 — with
GitHub Actions
Failure
…ai-dynamo#17068) Signed-off-by: Indrajit Bhosale <iamindrajitb@gmail.com>
Automated refresh from the public Dynamo Google Calendar. Generated by .github/workflows/community-events-refresh.yml. Signed-off-by: dynamo-ops <170655669+dynamo-ops@users.noreply.github.com>
…dynamo#17014) Signed-off-by: Piotr Tarasiewicz <ptarasiewicz@nvidia.com>
Signed-off-by: Zhan Xue <zhan.xue@intel.com>
…i-dynamo#17595) Signed-off-by: vanshil shah <49670736+vanshilshah97@users.noreply.github.com>
…l selection (ai-dynamo#17524) Signed-off-by: Sachal Malick <s@chal.ai> Signed-off-by: jthomson04 <jwillthomson19@gmail.com> Co-authored-by: Sachal Malick <s@chal.ai> Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
…7594) Signed-off-by: Dr. Stefan Schimanski <sschimanski@nvidia.com>
…i-dynamo#16751) Signed-off-by: Julien Darve <jdarve@NVIDIA.com>
…RPC (ai-dynamo#17032) Signed-off-by: svc-glamr@nvidia.com <svc-glamr@nvidia.com> Signed-off-by: GLAMR <svc-glamr@nvidia.com>
…i-dynamo#17523) Signed-off-by: hongkuanz <hongkuanz@nvidia.com> Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
…vLLM v0.32.0 (ai-dynamo#17402) Signed-off-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Signed-off-by: Pranjul Gupta <pranjulgupta0203@gmail.com> Signed-off-by: Dr. Stefan Schimanski <sschimanski@nvidia.com> Signed-off-by: devivasudevan <49675305+devivasudevan@users.noreply.github.com> Co-authored-by: Pranjul Gupta <pranjulgupta0203@gmail.com> Co-authored-by: devivasudevan <49675305+devivasudevan@users.noreply.github.com>
…eck (ai-dynamo#17526) Signed-off-by: Dmitry Tokarev <dtokarev@nvidia.com> Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
…ynamo#17350) Signed-off-by: Guan Luo <gluo@nvidia.com> Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
… to 0.17.3 (ai-dynamo#17536) Signed-off-by: Dmitry Tokarev <dtokarev@nvidia.com> Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
…dynamo#17465) Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
) Signed-off-by: Yao, Qing <qing.yao@intel.com> Signed-off-by: pallavi jaini <pallavi.jaini@intel.com> Signed-off-by: Pallavi Jaini <pallavi.jaini@intel.com> Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Co-authored-by: pallavi jaini <pallavi.jaini@intel.com> Co-authored-by: Claude Sonnet 5.5 <noreply@anthropic.com> Co-authored-by: Dmitry Tokarev <dtokarev@nvidia.com>
Signed-off-by: jain-ria <riajain@NVIDIA.com>
…te a PR (ai-dynamo#17471) Signed-off-by: Alec Flowers <aflowers@nvidia.com> Signed-off-by: Alec <35311602+alec-flowers@users.noreply.github.com> Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
ai-dynamo#15851) Signed-off-by: Biswa Panda <biswa.panda@gmail.com>
…amo#16981) Signed-off-by: doxu <doxu@nvidia.com>
Signed-off-by: Alec Flowers <aflowers@nvidia.com> Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: jthomson04 <jwillthomson19@gmail.com> Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: tanmayv25 <tanmay2592@gmail.com>
…mo#18000) Signed-off-by: svc-glamr@nvidia.com <svc-glamr@nvidia.com>
…ages (ai-dynamo#17925) Signed-off-by: Dmitry Tokarev <dtokarev@nvidia.com> Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
…i-dynamo#17963) Signed-off-by: Ege Cem Kirci <40044930+egecemkirci@users.noreply.github.com>
…rom suite (ai-dynamo#16798) Signed-off-by: Nate Mailhot <nmailhot@nvidia.com> Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
…i-dynamo#16570) Signed-off-by: Krishnan Prashanth <kprashanth@nvidia.com>
Signed-off-by: krishung5 <krish@nvidia.com>
…ge refresh (ai-dynamo#18064) Signed-off-by: Dan Gil <dagil@nvidia.com> Co-authored-by: Dmitry Tokarev <dtokarev@nvidia.com>
… builds (ai-dynamo#18021) Signed-off-by: svc-glamr@nvidia.com <svc-glamr@nvidia.com> Signed-off-by: GLAMR <svc-glamr@nvidia.com>
…emas (ai-dynamo#17518) Signed-off-by: Dr. Stefan Schimanski <sschimanski@nvidia.com>
…o#17064) Signed-off-by: neilkg <33635204+neilkg@users.noreply.github.com>
… traces (ai-dynamo#17516) Signed-off-by: Yuewei Na <nv-yna@users.noreply.github.com> Co-authored-by: Yuewei Na <nv-yna@users.noreply.github.com>
Signed-off-by: Yuewei Na <nv-yna@users.noreply.github.com> Co-authored-by: Yuewei Na <nv-yna@users.noreply.github.com>
…#17887) Signed-off-by: svc-glamr@nvidia.com <svc-glamr@nvidia.com> Signed-off-by: GLAMR <svc-glamr@nvidia.com>
…6474) Signed-off-by: svc-glamr@nvidia.com <svc-glamr@nvidia.com> Signed-off-by: GLAMR <svc-glamr@nvidia.com> Co-authored-by: Tushar Sharma <tusharma@nvidia.com>
…-dynamo#18077) Signed-off-by: Jacob Ioffe <jioffe@nvidia.com>
…ai-dynamo#18017) Signed-off-by: furionw <qiwa@nvidia.com> Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
…s the TRT-LLM mock does (ai-dynamo#18102) Signed-off-by: jthomson04 <jwillthomson19@gmail.com> Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: Jacky <18255193+kthui@users.noreply.github.com>
Signed-off-by: Jacky <18255193+kthui@users.noreply.github.com>
Signed-off-by: Jacky <18255193+kthui@users.noreply.github.com>
Signed-off-by: hongkuanz <hongkuanz@nvidia.com>
…i-dynamo#18140) Signed-off-by: doxu <doxu@nvidia.com>
…ted (ai-dynamo#18141) Signed-off-by: Sungsoo Ha <sungsooh@nvidia.com> Co-authored-by: Claude Sonnet 5.5 <noreply@anthropic.com> Co-authored-by: Yogendra Pandey <20666257+ynpandey-nv@users.noreply.github.com>
…dynamo#17707) Signed-off-by: Kyle McGill <kmcgill@nvidia.com> Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
…ze (ai-dynamo#18084) Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: jthomson04 <jwillthomson19@gmail.com> Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
…-dynamo#17625) Signed-off-by: neilkg <33635204+neilkg@users.noreply.github.com> Signed-off-by: doxu <doxu@nvidia.com> Co-authored-by: Neil Gollapudi <33635204+neilkg@users.noreply.github.com>
…sagg-decode-gate # Conflicts: # lib/kv-router/src/scheduling/queue.rs # lib/kv-router/src/scheduling/types.rs
ishandhanani
had a problem deploying
to
external_collaborator
November 5, 2026 02:46 — with
GitHub Actions
Failure
This branch had an error being deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
PR ai-dynamo#16618 added two separate things, and this PR is about the second:
BusyThresholds::has_room: a rank is full once the KV blocks its active requests hold exceeddecode_busy_threshold_fracof itstotal_kv_blocks, judged on the sharedLOADrow. feat(router): enforce busy-reject thresholds in the KV router queue ai-dynamo/dynamo#16619 and refactor(router): unify classifier inputs; deprecate absolute busy thresholds ai-dynamo/dynamo#16620 build on it: the router-wide--active-decode-blocks-thresholdmaps into this check on the reject path. (a) is correct in every topology, so this PR does not change it, the reject path, or the worker monitor.policy_classes[].decode_busy_threshold_fracin the router policy YAML, which the policy-class queue gate waits on. (b) is unreleased (not in any release branch or tag), and as merged it is correct only in aggregated serving.This PR implements (b) so it is correct in both topologies:
RoomChanged) that wakes the prefill queue. That signal does not share the decode actor'snotify_oneCapacityUpdates. The decode router books each decode leg that follows a remote prefill (RequestPhase::Decodewith staged KV) straight away: no class wait and no deadline expiry, because the leg's prefill is already running. Router-wide reject thresholds still apply when the decode worker is selected.Why this changes behavior: disaggregated KV routing has two policy-class queues in series, prefill then decode, and both get the same policy profile. As merged, the class decode limit did nothing at the prefill router, which never tracks held blocks. At the decode router it could hold a decode leg after its prefill was already dispatched. That held prefill KV in place, and broke SGLang bootstrap, where prefill and decode must run at the same time.
Design:
lib/kv-router: a newPairedPoolRoomhook that the host installs on a scheduler (set_paired_pool, likeset_selection_trace). In each gate pass the queue checks it together with the existing prefill check, in both the drain path and the never-queue direct path. Only classes with adecode_busy_threshold_fracuse it, and without a hook nothing changes. For requests without a LoRA, one answer is cached per class per gate pass.LocalScheduler::any_rank_has_roomreads booked load from the slot registry with no actor message, andsubscribe_room_changedexposes the broadcast hint. The hint fires on local releases, the actor's cleanup drain, peer-router state changes, and worker config changes.ScheduleRequest/SelectionOperationcarry an in-processadmitted_upstreamflag, so the queue books those requests directly. Wire DTOs (PreprocessedRequest,RouterConfigOverride) are unchanged.lib/llm: the frontend now installs the decodeRoutingHoston thePrefillRouterwhenever routing is KV, not only under conditional disagg. Every prefill binding's KV router gets a lazily resolvedDecodePoolRoom(it holds aWeak<KvRouter>). Until the decode host exists, the pool reports room, so nothing changes.RoutingHostmaps a decode leg withstaged_kv_cleanup(frontend-only,#[serde(skip)]) toAdmittedUpstream. A conditional-disagg bypass also hasRequestPhase::Decodebut has nothing staged, so the decode queue stays its gate and its behavior is unchanged.Decode-room eligibility (what the prefill hop applies):
decode_worker_id), allowed-worker hints, routing constraints, and the KV-transfer topology domain of the chosen prefill worker.RoutingEligibility,lib/kv-router/src/scheduling/filter.rs). So when the coarse gate admits a request, it is routed at decode exactly as before feat(router): add a decode busy threshold to policy-class queues ai-dynamo/dynamo#16618.Known limits and follow-ups:
Part of ai-dynamo#16543
Validation
All commands use a per-worktree
CARGO_TARGET_DIR.cargo fmt --all --check: clean.cargo clippy -p dynamo-kv-router -p dynamo-llm --all-targets -- -D warnings: pass, no warnings.cargo test -p dynamo-kv-router --lib: 1134 passed, 0 failed, 3 ignored.cargo test -p dynamo-kv-router --lib --features standalone-selection, which also runs the selection-core tests: 1393 passed, 0 failed, 3 ignored.cargo test -p dynamo-llm --lib kv_router::: 467 passed, 0 failed. The new end-to-end test also passed 5 of 5 repeated runs.cargo bench -p dynamo-kv-router --no-run: builds (4 bench targets). With--features standalone-selection,bench: builds (6 targets).cd lib/bindings/python && cargo check: pass.pre-commit run --files <changed files>, run throughuvx: 11 hooks passed, the rest skipped (no matching files).python3 docs/fern/scripts/docs_lint.py <changed page>: 0 errors. The 5 NAV warnings are on other, pre-existing pages.New tests:
scheduling::queue::tests::paired_pool_holds_until_its_room_signal_releases_the_request: the request stays held while the paired pool has no room. Room alone does not release it; the pool's room signal does, with no other capacity change.scheduling::queue::tests::paired_pool_rejects_a_never_queue_class_like_its_own_workers: the never-queue direct path and the queue agree.scheduling::queue::tests::paired_pool_is_ignored_by_classes_without_a_decode_limit: a class without a decode limit never consults the hook, and its prefill limit behaves as before.scheduling::queue::tests::admitted_upstream_skips_class_limits_but_not_reject_thresholds: the request is booked past a full class limit and ahead of the backlog, an already-passed deadline does not expire it, and reject thresholds still reject it.scheduling::local::tests::pool_room_reads_booked_decode_blocks_and_signals_releases: the direct read honors the worker filter, and the room signal fires on release even with queueing disabled.kv_router::routing_host::tests::disagg_decode_wait_limit_gates_the_prefill_hop_and_never_the_decode_hop: two real KV hosts share one policy file. Staged decode legs book past the class decode limit. A conditional-bypass-shaped decode request still waits at decode. A new prefill request waits at the prefill hop while decode is full, and freed decode KV releases it.kv_router::prefill_router::tests::kv_decode_host_resolves_the_decode_pool_without_conditional_disagg.Queue-gate benchmark for the aggregated path (
selection_coreno_hints_queue_gate, base 4cb0a16 vs this branch, shared host with load average 4 to 7):No regression within noise. The aggregated gate only adds one per-class array reset and one early-returning check per predicate.