Two Schedulers, One SLO A vLLM RFC from the llm-d team warns that disaggregated inference deployments, where prefill and decode run on separate schedulers, can trigger recomputation-based preemption inside the decode instance, forcing it to redo the full prefill work and all output tokens, which breaks end-to-end latency SLOs. The RFC highlights that in vLLM V1, recompute is the default preemption mode, and when the decode scheduler cannot see the prefill scheduler's admissions, it may evict requests whose KV cache was already discarded, causing redundant work and potential SLO violations. Two Schedulers, One SLO The previous post ended on a pattern: a memory hierarchy works because one component can see the whole path, and disaggregation splits that visibility across two vendors. Scheduling has the same shape, and it fails louder, because the scheduler is not merely optimising. It is the thing holding the system inside its latency budget. Continuous batching is a global algorithm Modern inference throughput comes from continuous batching. Rather than forming a batch, running it to completion, and forming the next one, the engine reconsiders the batch at every decoding step: finished sequences leave, waiting requests join, and the GPU never idles behind the slowest member of a fixed batch. vLLM, SGLang and TGI all work this way. Making that work requires the scheduler to see and control several things at once. It sees the waiting queue and decides what to admit. It sees KV memory , because PagedAttention allocates blocks on demand as sequences grow, so admitting a request is a bet on future memory. When the pool is fully committed the engine is KV-saturated and admits nothing further. And when the running set outgrows what the budget sustains, it preempts : evicting a request’s blocks, returning it to the waiting queue, and reallocating that memory to sequences that can finish. Preemption is the interesting one, because the recovery is not free. vLLM offers two modes. Swapping serialises the evicted blocks to host DRAM and copies them back on re-admission. Recomputation throws them away and re-runs prefill when the request is rescheduled. In vLLM V1, recompute is the default , on the reasoning that it is cheaper than moving blocks across PCIe. 1 fn:1 Every one of those decisions requires visibility into memory, the queue, and the running set simultaneously. That is fine when one process owns all three. Split it, and each half sees half Disaggregation gives you two engines with two schedulers, plus an external router deciding which instance gets what. Draw the state each can see and the problem is immediate. graph TB R "Router / orchestrator