2026/07/15 12.5k words

Transformer System #numinens#transformer#speculative-decoding#llm-serving#continuous-batching#vllm#goodput#kv-cache#scheduling#rollback

M7.8 - Speculative Serving: Scheduling, Evaluation, Release, and Rollback

M7.8 - Speculative Serving: Scheduling, Evaluation, Release, and Rollback

0x00 Overview And Background

The previous M7 articles established algorithms that can reduce the number of serial target-model rounds. They did not establish that enabling speculation on a shared server improves latency or capacity.

At production scale, speculation competes with batching:

Inter-request parallelism:
    put more requests in the target batch

Intra-request parallelism:
    put more candidate positions behind each request

The first source of work always advances another live request. The second source is useful only when candidates are accepted. Once the GPU is already well utilized by concurrent requests, speculative positions can displace useful request work and increase time per output token.

The owner question is:

How should a continuous-batching runtime choose speculative work, maintain exact per-request state, prove a serving win under changing load, and disable or roll back the feature without corrupting output or cache state?

Historical path to production control

The speculative-decoding lineage in A30 starts from an algorithmic asymmetry: an autoregressive target is expensive when asked for one new token, yet can score several already supplied candidate positions in parallel. M7.1 made the resulting probability contract explicit. M7.2-M7.7 then changed where candidates come from and how they are arranged. None of those facts determines how many speculative rows a shared server should schedule.

Production serving introduces a second lineage. Iteration-level batching and PagedAttention made request admission and KV ownership dynamic. The Synergy study then showed that batching and speculation are not additive knobs: the best draft length changes with batch size, model, and GPU. TurboSpec moved that observation into a closed loop combining an offline execution profile with online acceptance feedback. Current vLLM and TensorRT-LLM releases expose batch-size-dependent draft schedules, including an explicit zero-depth region. These are runtime mechanisms, not a proof that a particular schedule transfers between deployments.

Two later systems results sharpen the production contract. Batch Speculative Decoding Done Right identifies ragged acceptance as a synchronization problem: token positions, attention masks, and KV rows must all be realigned to the same logical prefixes. SPECTRE studies a different axis, placing the drafter on a remote shared service and overlapping drafting with verification. Together they show why “turn on speculative decoding” is not one operation. It is a versioned scheduler, tensor-layout, state-transaction, and placement decision.

The article therefore follows four questions in dependency order:

semantic:
    which final tokens and cache rows does one round own?

physical:
    which query rows, temporary buffers, and devices execute that round?

control:
    which measured feasible action maximizes useful service under load?

operational:
    which evidence permits release, disable, or rollback?
Algorithmic speculation becoming a versioned serving lifecycle through synchronization, profiling, control, and rollback

Continuous-batch speculative expansion

Background knowledge: the serving unit is not “one request, one token” anymore

Ordinary decode contributes one query token per active request. A speculative round contributes a variable number of candidate query rows per request.

For active request set and request-specific speculative depth :

represents method-specific anchor or frontier rows included in the target call. Its exact value depends on how logits and KV are aligned. The implementation must profile its actual query count rather than assuming every method maps to exactly rows.

The useful output from that work is ragged: one request may accept four candidates, another none, and a third may not speculate at all.

0x01 Claim Status And Scope

ClaimStatusEvidenceSafe interpretation
The best speculation length depends on batch size, model, hardware, and acceptance behavior.Externally verifiedSynergy of Speculative Decoding and Batching; TurboSpec; vLLM docsFixed is a deployment point, not a universal optimum.
Increasing concurrency generally calls for reducing speculative depth.Externally verified and runtime-specificSynergy paper; TurboSpec; current vLLM dynamic-SD docsThe precise breakpoints must be profiled per deployment.
is a valid and often necessary scheduler decision.Externally verifiedTurboSpec; current vLLM dynamic-SD docsThe server should bypass proposal and verification expansion when speculation loses.
A request can resume model-based speculation immediately after draft prefill/cache maintenance was skipped.False in generalTurboSpec; state derivation belowThe draft cache must be backfilled, re-prefilled, or the request must stay non-speculative.
Accepted output tokens and target KV rows always advance by the same count in a speculative round.FalseM7.1; TurboSpec cache discussionA bonus or correction token can be emitted before its own KV row is materialized.
Theoretical losslessness implies bit-identical logits and tokens across every batch shape and device.Falsecurrent vLLM documentationFloating-point order, batching, and nondeterminism can cause numerical differences.
Batch-size-1 speedup predicts high-QPS goodput.FalseSynergy paper; TurboSpec; 2026 latency modelLow-load fixed-cost gains can be erased by load-dependent service demand.
Average acceptance rate alone is enough to control speculation.FalseTurboSpec and derivations belowDepth distribution, batch size, proposal cost, target shape, memory, and SLOs matter.

This article owns deployment integration and release operations. It does not re-derive the proposal algorithms in M7.7 or the exact one-sequence sampler in M7.1.

M5.2 owns the ordinary versioned iteration plan, queue/admission policy, fairness service, and SLO denominators. M7.8 extends that decision surface with optional candidate rows, temporary branch state, and K=0; it does not replace M5.2’s base scheduler contract.

0x01A Ownership firewall

ConcernOwnerWhat M7.8 may consumeWhat M7.8 must not duplicate
Ordinary admission and fairnessM5.2immutable iteration plan, token budget, preemption semanticsredesign the base scheduler
Exact sequence samplingM7.1accepted prefix and frontier-token resultre-derive rejection sampling
Tree masks and branch verificationM7.2compiled candidate rows and accepted pathredefine ancestry masks
Proposal source and topologyM7.7typed proposal artifact and cost metadatarank or train proposal methods again
Speculative servingM7.8 ownsall of the above as inputsdelegate state, evaluation, or rollback to an algorithm paper

The runtime boundary is especially important. M5.2 decides which ordinary requests can receive service. M7.8 can spend optional rows inside that decision, but cannot let speculative work bypass age, priority, tenant, or SLO accounting. A request that receives one useful token with K=0 has received service; a request that consumes five candidate rows and accepts none has consumed resources without equivalent useful progress.

0x01B Immutable Serving Manifest And Round Plan

A serving profile is valid only for the exact objects that produced it. Model name strings are insufficient: two files with the same architecture can differ in vocabulary mapping, proposal layers, quantization, kernels, graph captures, or scheduler semantics.

@dataclass(frozen=True)
class SpecServingManifest:
    target_checkpoint_hash: str
    target_config_hash: str
    tokenizer_hash: str
    proposal_method: str
    proposal_artifact_hash: str | None
    verifier_algorithm: str
    sampler_contract_hash: str

    engine_version: str
    kernel_build_hash: str
    hardware_topology: tuple[str, ...]
    parallel_topology: tuple[int, int, int]  # TP, PP, EP
    kv_dtype: str
    graph_bucket_hash: str

    profile_generation: str
    profile_hash: str
    controller_version: str
    acceptance_schema: str
    release_epoch: int

The mutable request state points at that immutable manifest:

@dataclass
class RequestSpecState:
    request_id: str
    manifest_hash: str
    committed_token_count: int
    target_kv_length: int
    draft_kv_length: int | None
    pending_frontier_token: int | None
    proposal_ready: bool
    finished: bool
    rng_counter: int
    state_generation: int
    last_committed_round: int


@dataclass(frozen=True)
class SpecRoundPlan:
    iteration_id: int
    request_ids: tuple[str, ...]
    K_by_request: tuple[int, ...]
    query_rows_by_request: tuple[int, ...]
    target_blocks_reserved: tuple[tuple[int, ...], ...]
    draft_blocks_reserved: tuple[tuple[int, ...], ...]
    graph_bucket: str
    profile_generation: str
    controller_observation_cutoff: int

The plan is immutable after workers begin execution. Completions, cancellations, new arrivals, or controller updates belong to the next scheduler iteration. This is the same iteration-plan rule used by M5.2, extended with speculative shape and temporary-state ownership.

Before dispatch, validate:

def validate_round(manifest, requests, plan, profile):
    assert hash_manifest(manifest) == requests.common_manifest_hash()
    assert plan.profile_generation == manifest.profile_generation
    assert profile.supports_exact_shape(plan.graph_bucket, plan.K_by_request)
    assert all(k >= 0 for k in plan.K_by_request)
    assert target_blocks_fit(plan.target_blocks_reserved)

    for req, k in zip(requests, plan.K_by_request):
        assert not req.finished
        if k > 0 and method_needs_draft_kv(manifest.proposal_method):
            assert req.proposal_ready
            assert req.draft_kv_length == req.target_kv_length == req.committed_token_count
            assert req.pending_frontier_token is None

The draft/target/output equality is the strict dispatch convention used here. Other runtimes may fuse repair into the next forward, but must declare each model’s pending suffix. A one-token target frontier does not imply a one-token draft deficit: full acceptance can leave two draft rows missing. Cache presence alone is not proposal readiness.

Immutable model, runtime, profile, controller, and request-state generations for a speculative serving round

0x02 Derive Useful Tokens Per Speculative Round

Assume a constant conditional acceptance probability for each proposed token and a maximum draft length . This independence assumption is a teaching and control-model approximation; real acceptance is depth-, context-, and method-dependent.

The following full-round output moments assume no EOS or length limit suppresses an accepted token or the final correction/bonus. Section 0x09 handles stopped rounds separately; their output growth is not unconditionally .

Let be the accepted draft-prefix length. Token is accepted only if the first proposals are all accepted:

Use the tail-sum identity for a non-negative integer random variable:

The target verifier also emits one target-governed frontier token: either a correction at the first rejection or a bonus token after all drafts are accepted. Therefore:

with limit as .

Renderer-safe form:

E[accepted_drafts] = alpha + alpha^2 + ... + alpha^K

E[committed_output_tokens]
    = 1 + E[accepted_drafts]
    = (1 - alpha^(K+1)) / (1 - alpha)

0x02A Worked Acceptance Ledger

For :

Additional proposed rowsMarginal expected output from next proposal
01.0000-
11.70010.700
22.19020.490
32.53330.343
42.77340.240
52.94150.168

Each additional candidate has declining expected utility. Its compute and temporary-state cost does not decline in the same way.

0x02B Derive The Full Accepted-Length Distribution

The mean hides the raggedness that the scheduler must execute. Let be the conditional probability that candidate is accepted given that candidates were accepted. Define the survival probability:

For , exactly drafts are accepted when the first survive and candidate fails:

All drafts are accepted with probability:

The masses telescope:

One target-governed frontier token is emitted in either case, so the committed output count is . The first two moments are:

The constant- expression earlier is the special case . A controller needs the general form because depth-4 acceptance is conditioned on a request surviving depths 1-3; it is not estimated from all requests in the batch.

def accepted_prefix_pmf(alpha_by_depth, K):
    pmf = []
    survival = 1.0
    for j in range(K):
        pmf.append(survival * (1.0 - alpha_by_depth[j]))
        survival *= alpha_by_depth[j]
    pmf.append(survival)  # all K accepted
    assert abs(sum(pmf) - 1.0) < 1e-12
    return pmf

Why retain the variance of committed output? Two actions can have the same mean goodput but different round-time and progress variance. The higher-variance action can amplify tail inter-token latency, graph-bucket imbalance, and cross-request synchronization. Mean-only control is therefore a first approximation, not a release criterion.

Accepted-prefix survival probabilities becoming a normalized committed-output distribution with mean and variance

0x02C Goodput And Three Different Token Rates

For one serving step:

For batch with per-request acceptance estimate and depth :

Unlike raw processed-token throughput, goodput excludes rejected candidate rows.

Keep three counters separate:

processed query rows:
    target and proposal positions executed by kernels

committed output tokens:
    accepted drafts plus target-governed frontier tokens

SLO-qualified output tokens:
    committed tokens delivered while their request remains within policy

TurboSpec’s goodput uses the second numerator. A production dashboard may also need the third; otherwise a controller can improve aggregate token rate while starving an old request or worsening p99 inter-token latency. This article uses goodput for committed output per wall-clock time and names any SLO-filtered metric explicitly.

0x02D Estimation Bias And Censoring

Depth statistics are censored by earlier rejection. The estimator for is:

not . A controller that reduces also stops observing deeper positions, creating policy-dependent missing data. Therefore record the action that generated every observation and use controlled probes or hierarchical fallback before concluding that an unobserved depth is poor.

0x03 Continuous Batching Meets Ragged Acceptance

Continuous batching removes completed requests and admits new requests at scheduler iterations rather than waiting for a fixed request batch to finish. Speculation changes the scheduler’s work unit from one decode row to a request-specific block.

request r1: K=4, accepts 4 + bonus output
request r2: K=4, accepts 1 + correction output
request r3: K=0, ordinary one-token decode
request r4: prompt lookup proposes only 2 rows

The output lengths, target branch-cache commit lengths, draft-cache rollback points, and next input positions are all different.

Ragged output and KV frontier

0x03A Logical Request State

Each request needs at least:

committed_token_count
target_kv_length
pending_frontier_token or none

proposal_enabled
proposal_method
proposal_kv_length or retrieval cursor
proposal_checkpoint/index version

current_K
acceptance statistics by depth
temporary target-branch allocation
sampling RNG state

The invariant is not always:

committed_token_count == target_kv_length

When the verifier emits a correction or bonus token from a target distribution, that token can be appended to the output before the token itself has been processed as an input row. A safe state is:

The next valid target call must materialize the frontier token’s KV before later tokens depend on it.

0x03B Per-Request Commit Record

@dataclass
class SpecCommit:
    request_id: str
    accepted_draft_rows: list[int]
    emitted_frontier_token: int | None
    target_kv_rows_to_commit: list[int]
    target_kv_rows_to_discard: list[int]
    draft_rollback_length: int | None
    proposal_can_resume: bool


def apply_commit(req, commit, target_branch_cache):
    assert forms_prefix(commit.accepted_draft_rows)

    req.target_cache.commit_rows(
        target_branch_cache,
        commit.target_kv_rows_to_commit,
    )
    target_branch_cache.discard(commit.target_kv_rows_to_discard)

    if commit.emitted_frontier_token is not None:
        req.output.append(commit.emitted_frontier_token)
        req.pending_frontier_token = commit.emitted_frontier_token

    if req.draft_cache is not None:
        req.draft_cache.truncate(commit.draft_rollback_length)

    req.proposal_enabled &= commit.proposal_can_resume

This is a cache/frontier fragment of the larger atomic publication transaction: the omitted accepted-output step must already have appended the emitted accepted draft tokens before this fragment appends the frontier. It is not a complete standalone output publisher. The stopping rule must first truncate both the accepted-output list and its target-row commit map. proposal_can_resume must reflect actual cache repair and terminal status, not merely cache allocation.

The frontier’s KV materialization, unlike its output publication, can be eager or deferred. Section 0x09 uses deferred materialization and separate pending suffixes for the target and drafter.

0x03C Ragged Acceptance Is A Synchronization Problem

For a nonterminal full round, request advances by output tokens but only candidate-input rows are immediately available for target-KV commit. The batch is therefore ragged in two coordinates: logical output length and materialized target-KV length.

Ragged accepted prefixes create different logical lengths inside one batch

Source: Batch Speculative Decoding Done Right, ragged-tensor overview. The figure motivates the synchronization problem; its implementation and benchmark claims remain source-reported.

For each request, define:

The final +1 is the pending correction or bonus frontier. A rectangular physical batch can pad these lengths, but padding must not become logical history. Three invariants close the mapping.

Position invariant. The visible non-padding tokens for request have contiguous logical positions . Padding locations never reuse or advance a logical position.

Mask invariant. A query row can see exactly the committed prefix and its allowed candidate ancestors. It cannot see batch padding, a rejected suffix, or another request’s realignment rows.

KV invariant. Every committed target-KV row identifies the same request, token, logical position, ancestor path, layer, dtype, and cache generation as the corresponding reference decode. The frontier token is not represented by the rejected candidate’s KV row.

These invariants explain why a shape-correct implementation can still generate wrong output. Position IDs may point through padding; a stale attention mask may expose rejected rows; or a copied KV block may retain the old physical offset after the logical sequence moves.

0x03D Rectangularization Alternatives

StrategyCorrectness conditionSystems costTypical failure
Mask in placebackend supports arbitrary interior gaps and exact positionslittle copying, complex kernelsstale mask or non-contiguous position semantics
Roll back whole batchdiscard every row beyond common accepted lengthsimple common shapethrows away valid work from successful requests
Unpad, append, repadrebuild IDs, masks, and KV maps from logical prefixessynchronization and copy/reindex costpartial update across the three invariants
Length-grouped poolexecute requests with compatible logical lengthsqueueing and grouping complexitystarvation or too-small groups
Paged indirectionlogical block table points to per-request physical rowsmetadata and gather/scatter costaliasing stale block generations

The correctness-first unpad/append/repad construction is:

def synchronize_verified_batch(batch, verification):
    logical = []
    for req, result in zip(batch.requests, verification):
        prefix = read_logical_prefix(req)
        accepted = result.accepted_draft_tokens
        frontier = result.frontier_token

        commit_target_rows(req, result.target_rows[:len(accepted)])
        discard_target_rows(req, result.target_rows[len(accepted):])
        logical.append(prefix + accepted + [frontier])

    width = max(map(len, logical))
    token_ids, position_ids, masks, block_tables = repad(logical, width)
    assert_positions_masks_and_kv_agree(
        token_ids, position_ids, masks, block_tables
    )
    return token_ids, position_ids, masks, block_tables

Unpad, append accepted output, repad, and realign KV ownership

Source: Batch Speculative Decoding Done Right, unpad-append-repad process. The article uses the figure to expose state that must move together, not to prescribe one universal storage layout.

Realignment is not free. If physical KV blocks must be remapped or copied, a simplified cost ledger is:

This term belongs in the measured round cost. Treating it as scheduler overhead outside the speculative objective systematically overestimates goodput.

Accepted prefixes becoming synchronized token positions, attention masks, block tables, and frontier ownership

0x04 Batch Expansion And The Pressure

Let be the number of active decode requests. A fixed-depth sequence proposer with candidate rows creates approximately:

target query rows, with method-specific alignment details. Current vLLM dynamic speculative-decoding documentation describes the same operational pressure as effective batch size : beyond a hardware-dependent critical region, speculative verification hurts time per output token.

The important distinction is:

scheduler batch size:
    active requests

target query-row count:
    all anchor, candidate, and repair rows

useful output count:
    accepted prefixes + target frontier tokens

Two batches with the same request count can have very different target shapes if their , tree sizes, prompt-lookup hits, or repair paths differ.

0x04A Why Larger Batches Prefer Smaller

The Synergy paper models expected accepted draft tokens as a sublinear function:

and target verification time at fixed batch size with a local linear approximation:

Including sequential draft cost , time to generate output tokens is approximated by:

As grows, the marginal target slope and draft cost generally grow because more parallel rows already occupy compute. The numerator’s penalty for another proposal rises, while the denominator remains sublinear. The minimizing therefore moves downward.

This derivation is a local model, not a universal latency law. Real kernels have plateaus, graph buckets, memory cliffs, and topology effects. Its value is explaining the direction that profiling repeatedly observes.

Measured per-token latency over batch size and speculation length

Source: The Synergy of Speculative Decoding and Batching in Serving LLMs, Figure 1. Each curve is a batch size and each star is that curve’s best measured speculation length. Across the reported model/GPU combinations, larger batches usually shift the optimum toward shorter drafts. The exact optimum is configuration-specific; the recurring shape is the evidence for profiling and jointly.

0x05 Profile The Execution Surface

A production controller needs an offline latency surface, not a scalar “draft is 10x smaller” claim.

For target model/hardware configuration , TurboSpec uses a profile over context and batched query tokens, with a fitted teaching form:

The terms summarize KV loading, query-token computation, and fixed model/system cost. Actual deployment should retain measured residuals and use richer buckets when the linear form misses graph or kernel transitions.

profile_key = (
    target_checkpoint,
    draft_checkpoint_or_method,
    dtype_and_quantization,
    cache_schema_and_qspec,
    allocation_and_retention_policy,
    tensor_parallel_degree,
    kernel_build,
    gpu_type,
    graph_capture_mode,
)

for context_bucket in CONTEXT_BUCKETS:
    for request_batch in REQUEST_BATCHES:
        for K in SPEC_DEPTHS:
            measure(
                target_verify_latency,
                draft_latency,
                temporary_kv_bytes,
                peak_memory,
                graph_capture_hit,
            )

Serving latency surface

0x05A Memory Feasibility Before Goodput

For homogeneous full K/V rows, request with candidate-node count has the following approximate temporary target code payload, with in bytes per scalar:

This product is not a generic quantized/MLA/shared-page cache allocator. Admission replaces it with the actual incremental allocation-union delta for the schema’s per-layer retained segments: codes, qparams, residual/sparse state, page rounding and sharing counted once. M8.6 owns quantized representation, M5.8 latent representation, and M5 retention/publication/lifetime.

The following capacity ledger requires disjoint categories: resident excludes separately listed committed K/V and workspace, temporary K/V means new allocations not already in committed/shared state, and logits/sampling/ proposal workspace is charged once. The candidate action set must first satisfy:

Only feasible values should enter the goodput optimizer. Relying on OOM recovery in the critical path is not a control policy.

The paper statement that draft length does not enlarge the persistent KV cache and the ledger above are compatible. Candidate depth does not permanently append rows per round. It can still increase transient target rows, attention workspace, logits, branch block reservations, and allocator rounding. Measure persistent KV, reserved branch KV, and ephemeral workspace separately.

0x05B A Profile Is A Measured Domain, Not A Formula

The profile key must include every variable that can change kernel selection or state cost:

ShapeKey(
    proposal_method,
    request_batch_bucket,
    context_token_bucket,
    query_rows,
    candidate_nodes,
    K_bucket,
    target_dtype,
    kv_dtype,
    cache_schema_and_qspec,
    allocation_and_retention_policy,
    TP, PP, EP,
    graph_bucket,
    adapter_mix_bucket,
    prefix_cache_state,
)

For each shape, collect more than one mean:

warm-up until graph capture and allocator state are stable
record proposal / transfer / target / select / sync / repair separately
record p50, p95, p99 and sample count
record peak allocated and peak reserved memory
record graph hit, kernel IDs, and target query-row count
retain residuals from any fitted model

Use blocked randomization when profiling several values so thermal state, clock drift, and background load do not always favor the same action. Store raw samples or sufficient statistics with the profile generation.

TurboSpec’s linear teaching model can be written:

For measured sample , the residual is:

The model is acceptable only inside a declared support region and while its residual distribution remains bounded. Graph-capture transitions, kernel changes, allocator cliffs, and expert-routing changes can produce piecewise behavior that one global plane cannot represent.

def predict_round(profile, shape):
    bucket = profile.exact_or_declared_interpolation(shape)
    if bucket is None:
        raise OutOfProfileSupport(shape)
    estimate = bucket.predict(shape)
    return Estimate(
        mean=estimate,
        upper=estimate + bucket.residual_quantile(0.95),
        profile_generation=profile.generation,
    )

An out-of-support shape must fall back to K=0, a conservative captured bucket, or an explicitly labeled exploration request. Silent extrapolation is not a performance optimization; it is an unreviewed policy change.

A speculation-aware cost model restores a common load-latency relationship

Source: An Interpretable Latency Model for Speculative Decoding in LLM Serving, Figure 4. One shared cost pair fails across draft lengths and acceptance rates; stage-aware effective costs recover the measured relationship. The fitted coefficients are configuration-specific.

Measured shape buckets, fitted latency surface, residual envelope, and explicit out-of-support fallback

0x05C Profile Invalidation

Invalidate or quarantine a profile after any manifest change affecting execution:

target or proposer weights / quantization
tokenizer or sampler contract
engine, compiler, kernel, driver, or graph build
GPU type, TP/PP/EP topology, or placement
KV dtype, block size, memory reserve, or adapter path
material workload shift outside calibrated context and shape buckets

Online residual monitoring can detect drift without pretending to identify its cause. If observed round time repeatedly exceeds the stored upper envelope, disable speculation first, preserve evidence, and re-profile offline.

0x06 Load Emerges From Arrival Rate

Batch size in a continuous server is an outcome of arrivals, service time, KV pressure, and scheduler policy. A 2026 serving study models stable pre-saturation request latency as:

where is effective load-independent cost and is marginal cost per effective active request. By Little’s Law:

for arrival rate . Substitute:

This is a pre-saturation steady-state approximation. It is not valid across the instability boundary where queues, preemption, and cache churn change sharply.

Measured speculative-serving latency collapses onto normalized request-rate scaling

Source: An Interpretable Latency Model for Speculative Decoding in LLM Serving, Figure 1. Measurements from several model and prefill/decode configurations collapse after normalization by fitted fixed and marginal service costs. This supports the Little’s-Law derivation inside the measured stable regime; it does not remove the need to detect saturation or refit after a runtime change.

0x06A Speculation Changes Fixed And Load-Dependent Costs Differently

Let and let a request need output tokens. It needs about speculative cycles. Split fixed costs into prefill, verifier, and drafter components:

and load-dependent costs:

Then:

Large can improve the low-load fixed-cost term by reducing verifier rounds, yet worsen the load-dependent term through more draft work and expanded target batches. This formally explains why batch-size-1 tuning often over-speculates at high QPS.

0x06B MoE Targets Add Expert-Coverage State

For an MoE verifier, expanding candidate rows can activate more distinct experts. At low load and small trees, only a sparse subset may be touched; wider verification increases expert coverage, communication, and device imbalance.

The 2026 latency paper models this as a correction to dense scaling. The operational lesson is sufficient here:

profile MoE target verification with real routing;
do not derive K from active parameter count alone;
record expert coverage, all-to-all bytes, and straggler rank time.

This reconnects M7 serving to M6.2 for routing and logical traffic, and to M6.6 for physical placement, collectives, kernels, and measured runtime.

Under the latency paper’s simplifying independent-uniform routing assumption, one expert is never selected by one routed token with probability , where experts are selected from . Across routed tokens:

Therefore the expected fraction of distinct experts touched is:

This is a modeling baseline, not a claim that trained routers are uniform or independent. Production traces should replace with measured expert sets, tokens per expert, all-to-all bytes, and slowest-rank time.

0x06C Stability Margin And Saturation Gate

The closed form has a stability condition:

Define the stability margin:

Then sensitivity to arrival rate is:

As the margin approaches zero, tiny load or model errors produce large latency errors. The controller must not optimize a smooth model through that boundary.

def stable_latency(arrival_rate, C1, C2, min_margin):
    margin = 1.0 - arrival_rate * C2
    if margin < min_margin:
        raise SaturationRisk(margin)
    return C1 / margin

Operational saturation signals include sustained queue growth, rising preemption, cache churn, admission delay, profile residual drift, and a widening p95/p99 gap. On entry, force conservative shapes or K=0; do not wait for the mean-latency model to predict an impossible denominator.

0x06D Arrival Processes And Burst Limits

Little’s Law relates long-run averages under a stable system; it does not say that arrivals are Poisson, that service times are independent, or that a burst has already reached steady state. Evaluate at least:

closed-loop concurrency:
    next request begins after one completes

open-loop stationary arrivals:
    fixed rate with controlled inter-arrival distribution

bursty arrivals:
    on/off or trace replay with the same mean rate

correlated long outputs:
    service demand and active batch remain coupled for many iterations

The same average QPS can yield different queue and batch distributions. A release profile must name its arrival process rather than reporting “QPS=8” as a complete workload specification.

Stable request-rate model approaching a saturation boundary where queue growth and tail latency invalidate extrapolation

0x07 A Goodput Controller

TurboSpec combines an offline execution profile with online acceptance feedback. At each generation step it evaluates candidate speculative depths and selects the highest estimated goodput, including .

TurboSpec offline profiler, online adapter, scheduler, proposer, verifier, and sampler

Source: TurboSpec, Figure 7. The offline profiler estimates execution cost; the online adapter combines that profile with observed acceptance; the scheduler chooses a supported shape; and propose, score, and accept remain separate runtime stages. Draft and target KV state are shown as distinct resources.

Goodput control loop

def choose_spec_depth(batch, profile, acceptance_model, memory):
    best = Decision(K=0, predicted_goodput=baseline_goodput(batch, profile))

    for K in supported_depths(batch.method):
        if not memory.fits(batch, K):
            continue
        if not profile.has_shape(batch, K):
            continue

        expected_tokens = sum(
            acceptance_model.expected_commits(req, K)
            for req in batch.requests
        )
        predicted_time = profile.predict_round(batch, K)
        goodput = expected_tokens / predicted_time

        if goodput > best.predicted_goodput + HYSTERESIS_MARGIN:
            best = Decision(K=K, predicted_goodput=goodput)

    return best

0x07A Constrained Action Space

The controller does not optimize over integers in isolation. One action is a physical execution choice:

where is maximum path depth, is total candidate rows, is a captured shape bucket, and is a placement or coordination mode. A linear draft has ; a tree does not.

Define the feasible set for current server state by:

manifest compatibility
profile support for the exact physical shape
target and draft cache readiness
target token-row budget
temporary KV and workspace budget
captured graph / backend support
parallel topology and sampling-feature support
base scheduler fairness and SLO constraints

Then choose:

LCB is a lower-confidence estimate of committed useful output and UCB is an upper-confidence estimate of round time. This conservative ratio prevents an uncertain action from winning merely because its point estimate is optimistic. K=0 must always remain in and carries directly measured baseline cost.

def choose_action(state, actions, profile, acceptance):
    feasible = [a for a in actions if all_constraints_hold(a, state)]
    assert any(a.K == 0 for a in feasible)

    scored = []
    for action in feasible:
        useful_lcb = acceptance.committed_tokens_lcb(action)
        time_ucb = profile.round_time_ucb(action)
        scored.append((useful_lcb / time_ucb, action))

    score, action = max(scored, key=lambda pair: (pair[0], -pair[1].K))
    return action, DecisionEvidence(score=score, profile=profile.generation)

The controller stores the complete candidate set, rejected constraints, point estimates, uncertainty bounds, and selected action. Without that decision record, an operator cannot distinguish a model error from an action that was never feasible.

Speculative serving controller filtering actions by compatibility, memory, profile support, fairness, and stability before conservative goodput selection

0x07B Acceptance Feedback Should Be Segmented

A single global acceptance moving average is simple but can mix incompatible traffic:

code completion vs conversation
temperature 0 vs temperature 1
short vs long context
adapter A vs adapter B
target checkpoint before vs after upgrade
prompt lookup hit vs miss

A production estimator should key statistics by the smallest set of dimensions that materially changes acceptance while retaining enough samples:

(proposal version, target version, sampler bucket,
 workload class, context bucket, adapter id optional)

Use hierarchical fallback when a bucket is sparse. Record acceptance by depth, not only one average:

Then:

This removes the constant- approximation from the controller.

For uncertainty, a Beta-Binomial teaching model is useful. With prior and observed accepted/rejected counts among requests that reached depth :

Use a posterior lower quantile for conservative useful-output prediction, not only the posterior mean. The model assumes exchangeability inside its bucket; distribution drift, correlated requests, and controller-selected censoring can violate that assumption. Those are reasons to segment, decay, and probe, not to interpret the posterior as a universal law.

0x07C Step-Level Versus Per-Request Control

GranularityBenefitCost
Deployment-wide fixed stable shape and simplest captureignores load and workload variation
Batch-size scheduleconstant-time lookup and captured bucketsrequests in one batch share an action
Step-level adaptive responds to current batch and acceptanceshape can change between iterations
Per-request spends rows on high-value requestsragged proposal/verification and graph fragmentation
Per-node tree budgetrichest opportunity allocationhighest compiler, metadata, and validation burden

The Synergy strategy and current dynamic-runtime schedules are naturally batch- or step-level. Per-request control is not automatically better: its extra raggedness and graph misses can cost more than the acceptance gain. The controller must optimize the implemented physical action, including grouping and padding, rather than an ideal independent vector.

Fairness remains request-based. Charge speculative rows to the request that caused them, but advance age/service accounting by committed useful progress. When reducing an over-budget plan, remove the row with the lowest conservative marginal utility while respecting minimum service for old or priority requests.

0x07D Hysteresis And Exploration

Without hysteresis, noisy estimates can alternate between and every step. Without occasional exploration, a controller that disables speculation after distribution drift may never discover recovery.

enable threshold:
    predicted gain > +epsilon_enable

disable threshold:
    predicted gain < -epsilon_disable

minimum dwell:
    hold decision for N rounds unless memory/SLO emergency

probe:
    route a small eligible fraction through candidate K

Exploration must respect request cache readiness. A model-based proposal cannot be re-enabled mid-request if its draft KV was allowed to fall behind, unless the runtime backfills it.

Every observation must carry:

manifest hash
controller and profile generation
chosen action and shape bucket
eligibility and fallback reason
depth reached / accepted / rejected
measured stage times and synchronization cost
request class and sampling bucket

Late results from an old policy epoch may be retained for forensic analysis but must not silently update the active controller.

0x08 Prefill And Draft-Cache Readiness

A separate draft model needs its own prefix KV cache. There are three policies.

Always prefill the draft

advantage:
    speculation may start at any decode round

cost:
    draft prefill runs even for requests that never speculate

Prefill only eligible requests

advantage:
    avoids work when high load predicts K=0

cost:
    request cannot later speculate without backfill/re-prefill

Lazy prefill on transition

advantage:
    pays only when the controller enables speculation

cost:
    transition latency spike; needs admission/SLO handling

TurboSpec describes a policy that can skip proposer prefill above a disable threshold. Because the draft KV is then absent, speculation remains disabled for those requests unless the system later resets/rebuilds the state.

def can_enable_model_draft(req):
    return (
        not req.finished
        and req.proposal_enabled
        and req.draft_cache is not None
        and req.draft_cache.token_count == req.target_cache.token_count == len(req.output)
        and req.pending_frontier_token is None
        and req.draft_version == ACTIVE_DRAFT_VERSION
    )

The equality may be replaced by a proved frontier convention, but it cannot be assumed away.

0x08A Explicit Cache-State Machine

Use named states instead of inferring readiness from nullable pointers:

StateTarget KVDraft KVFrontierMay speculate?
ALIGNEDthrough outputthrough outputnoneyes
TARGET_FRONTIERone behind outputmethod-dependentone tokenno until materialized
DRAFT_BEHINDthrough outputbehind targetnoneno until backfilled
SPEC_DISABLED_SYNCEDthrough outputthrough outputnonepolicy says no
SPEC_DISABLED_UNSYNCEDthrough outputabsent/stalenoneno
PREEMPTEDsnapshot-ownedsnapshot-ownedexplicitno until restore validates
FINISHEDretained prefix or releasedretained prefix or releasedmay remain recorded until releaseno; EOS/length stop is terminal

Allowed transitions are explicit:

ALIGNED --spec round--> TARGET_FRONTIER
TARGET_FRONTIER --target append--> ALIGNED or DRAFT_BEHIND
DRAFT_BEHIND --draft repair--> ALIGNED
ALIGNED --K becomes 0, maintain draft--> SPEC_DISABLED_SYNCED
ALIGNED --K becomes 0, skip draft--> SPEC_DISABLED_UNSYNCED
SPEC_DISABLED_UNSYNCED --re-prefill/backfill--> ALIGNED
any committed state --preempt--> PREEMPTED
PREEMPTED --validated restore--> prior logical state, new generation
any live state --EOS/length stop--> FINISHED (never proposal-ready)

No transition commits a correction or bonus token’s target KV from the rejected candidate row at the same physical position.

Target KV, draft KV, pending frontier, disabled, repaired, and preempted speculative serving states

0x09 Draft, Target, And Frontier Cache Transitions

TurboSpec partial-acceptance and all-accepted draft-cache repair paths

Source: TurboSpec §5.1 and Figure 8. A sequential drafter has not yet processed its final sampled proposal. Under partial acceptance (panel a), that proposal is rejected or discarded, so the draft model resumes from the correction token and materializes that token’s missing cache row. Full acceptance (panel b) instead requires draft-side processing of the final proposal as well as the bonus token. The dashed boxes are newly generated KV state, which is why output-token count and cache-row count cannot be conflated. The ledgers below derive the corresponding prefix lengths locally.

Cache convention and three separate prefixes

Start from a prefix of length already materialized in both models, with next-token logits available. A standard sequential drafter samples proposals without an extra forward on its final sampled token. It has therefore materialized only proposal rows. Target verification processes all candidate inputs, but only rows belonging to emitted accepted tokens may be committed.

For accepted proposals and an emitted correction/bonus (), before repair:

Here counts accepted draft tokens actually emitted; the no-stop examples below emit the whole accepted prefix. A cache row is model-specific: target verification does not create a draft-model row. An eager extra draft forward can make the final proposal row available, but its execution and cost must be recorded explicitly. Do not assume that variant silently.

Partial acceptance

Suppose , two drafts are accepted, the third is rejected, and correction token is emitted without stopping.

output append:       draft_1, draft_2, correction c
target KV retained:  prefix + draft_1 + draft_2
draft KV retained:   prefix + draft_1 + draft_2
target pending:      [c]
draft pending:       [c]
proposal ready:      false until both pending suffixes are processed

Discard rejected target rows and truncate the draft suffix before repair. Even if happens to equal a rejected token ID, do not treat token equality as proof that a discarded branch row has the required identity. Reject-first () uses the same rule with both retained caches ending at .

All accepted

Suppose all four drafts are accepted and the target emits bonus token , again without an EOS or length stop.

output append:       draft_1, draft_2, draft_3, draft_4, bonus b
target KV retained:  prefix + draft_1 + draft_2 + draft_3 + draft_4
draft KV retained:   prefix + draft_1 + draft_2 + draft_3
target pending:      [b]
draft pending:       [draft_4, b]
proposal ready:      false

The fully accepted drafter is two rows behind output, not one. Process draft_4 and then b through the draft model in causal order (or an equivalent causally masked two-token forward). Materializing only the target’s bonus row does not repair the draft cache.

For the synthetic , , example:

StageOutput lengthTarget KV lengthDraft KV lengthProposal ready?
After publication151413no
After target processes bonus 151513no
After draft processes draft_4151514no
After draft processes 151515yes, if policy/version checks also pass

Repair appends cache rows, never duplicate output tokens. The target and draft repairs can be scheduled separately, but the strict readiness gate opens only when both caches represent the entire visible prefix.

EOS and length-limit stopping

Apply the stopping rule before publication. Emit no tokens after EOS, and no more than the remaining output budget. If stopping occurs within accepted drafts, omit the correction/bonus and discard all later candidate rows.

Let be the number of accepted drafts actually emitted after stopping truncation and let indicate an emitted frontier. Under the same sequential-drafter convention:

For example, a length cap reached exactly at draft_4 yields for , without a bonus. EOS or a length cap at the bonus instead leaves .

A terminal request is never proposal-ready, even if all lengths happen to match. Retained caches may still lag the final output; keep that state explicit until release. No continuation repair is required merely to finish the request. A separate cache-reuse/export policy may choose additional work, but must not silently reopen decoding. A zero remaining budget dispatches no round.

No speculation

K = 0:
    ordinary target token, no proposal branch
    its target row may still be pending after output publication
    if a compatible draft cache exists, maintain or backfill it explicitly
    if draft KV is absent, target repair does not recreate it

The toy cache oracle is scoped to a separate sequential autoregressive drafter. Retrieval proposers, integrated heads, tree layouts, and runtimes with an incoming anchor offset need their own explicit state mapping. This prefix ledger is not a claim that all proposal methods share the same cache layout.

0x09A Prepare, Execute, Publish

Cache mutation is a transaction:

def run_spec_round(req, action, workers):
    snapshot = req.snapshot_identity_and_lengths()
    reservation = reserve_branch_blocks(req, action)
    try:
        proposal = workers.propose(req, action)
        verification = workers.target_verify(req, proposal, reservation)
        decision = exact_accept_or_method_verify(req, proposal, verification)

        commit = build_commit_record(snapshot, proposal, verification, decision)
        validate_commit(commit, snapshot, req.manifest_hash)
        publish_atomically(req, reservation, commit)
        return commit
    except BaseException:
        reservation.discard_all()
        assert req.matches(snapshot)  # no partial publication
        raise

publish_atomically means that output tokens, target block table, draft rollback point, pending frontier, RNG counter, and state generation become visible together. The GPU operations may complete at different times; the request-visible metadata publication may not.

0x09B Preemption, Resume, And Duplicate Completion

A preemption snapshot contains logical state, not raw pointers:

request and manifest hash
committed output token IDs or durable reference
target/draft logical KV lengths and block generations
pending frontier token
sampler RNG counter
last committed iteration and state generation
controller eligibility state

On restore, physical blocks may change. Rebuild block tables, then validate the same token/position/layer generation contract before dispatch. A worker result is publishable only when its (request_id, iteration_id, state_generation) matches the active request. Duplicate or late completion is discarded idempotently.

def may_publish(result, req):
    return (
        result.request_id == req.request_id
        and result.iteration_id > req.last_committed_round
        and result.base_generation == req.state_generation
        and result.manifest_hash == req.manifest_hash
    )

0x0A Request Scheduling Policy

A scheduler should treat speculative work as optional query-token demand.

def build_iteration(waiting, running, token_budget, temp_kv_budget):
    batch = admit_prefill_and_decode(waiting, running, token_budget)

    spec_candidates = []
    for req in batch.decode_requests:
        if not request_is_spec_eligible(req):
            req.K = 0
            continue

        req.K = controller.choose_K(req, batch)
        spec_candidates.append(req)

    while estimated_query_rows(batch) > token_budget:
        req = lowest_marginal_goodput_request(spec_candidates)
        req.K = reduce_K(req.K)

    while estimated_temp_kv(batch) > temp_kv_budget:
        req = lowest_marginal_goodput_request(spec_candidates)
        req.K = reduce_K(req.K)

    return bucket_for_executable_shapes(batch)

0x0AA Marginal Utility

For request , the expected output gain from increasing to under depth-specific acceptance is:

The scheduler should compare that gain with marginal target, draft, memory, and shape-fragmentation cost. Requests with poor next-depth acceptance should lose speculative rows before high-confidence requests.

0x0AB Shape Buckets And CUDA Graphs

Dynamic creates many execution shapes. Padding every request to the maximum wastes work; fully ragged execution can defeat graph capture and kernel regularity.

Design choices:

PolicyBenefitCost
One per batchSimple dense shapePer-request opportunity lost
Bucket requests by Better fit and graph reuseMore sub-batches/kernel launches
Pad to nearest captured Bounded shape setSome rejected/padding work
Fully ragged custom kernelFine-grained controlHigh implementation and validation burden

Current vLLM documentation exposes batch-size ranges mapped to a configured optimal , including . It also documents method and CUDA-graph limitations. These are version-specific implementation facts, not speculative-decoding laws.

0x0B Placement And Distributed Execution

Proposer and verifier placement choices

Colocated draft and target

advantages:
    low proposal transfer latency
    simpler request ownership

costs:
    draft weights/KV reduce target KV capacity
    draft kernels contend with target work

Dedicated draft device

advantages:
    draft can overlap or avoid target-memory pressure

costs:
    tokens, probabilities, state, and control cross devices
    synchronization can dominate a very small drafter

CPU or host retrieval proposer

advantages:
    no neural draft weights on GPU

costs:
    index latency and host-to-device candidate transfer

Integrated head, EAGLE, or MTP

advantages:
    target representation already resident

costs:
    proposer checkpoint is tightly coupled to target architecture/version
    feature or module state needs its own runtime path

Distributed compatibility must be tested against the exact engine release. Current vLLM documentation lists known version-specific incompatibilities and supported methods; do not convert that table into a permanent architectural claim.

0x0BA Ordinary/Parallel Coordination

Serial draft/verify execution preserves the latest target result before the next proposal. Overlapped execution can hide draft time, but it may prepare a continuation from a prefix later invalidated by verification.

SPECTRE analyzes a batch of size , candidate segment length , draft step time , target verification time , accepted output per round , and invalidated-request fraction . Under its stated assumptions, ordinary speculative decoding has:

When , parallel drafting can be hidden by verification. The fraction that cannot reuse its pre-generated segment contributes one fallback token, while the rest contributes :

Solving gives the paper’s critical invalidation ratio:

Parallel coordination is favored only when under this model. The derivation assumes a specific pipeline, steady stage times, , and hidden draft work. Network delay, queueing at a shared drafter, variable batch shape, and failed overlap require measured terms rather than an unqualified reuse of the threshold.

Ordinary and parallel remote-drafting pipelines

Source: SPECTRE, ordinary/parallel coordination figure. The diagram makes overlap and invalidated draft work visible; its timing comparison inherits the paper’s pipeline and workload assumptions.

Remote multi-tenant drafter, speculative priority scheduling, and hybrid coordination

Source: SPECTRE, Figure 1. The system reuses a small-model service as a remote drafter and switches coordination modes. Reported throughput and resource results remain specific to the paper’s implementation and workload.

0x0BB Remote Protocol And Failure Epoch

Remote proposals need a typed envelope:

RemoteDraftRequest(
    request_id,
    target_iteration,
    base_state_generation,
    manifest_hash,
    prefix_digest,
    max_depth,
    deadline,
)

RemoteDraftResult(
    request_id,
    target_iteration,
    base_state_generation,
    proposal_tokens,
    proposal_probabilities_or_absent,
    drafter_queue_ms,
    drafter_compute_ms,
)

The target never blocks past the request’s speculation deadline. Timeout, version mismatch, stale generation, malformed probability semantics, or remote overload falls back to the already feasible local action, usually K=0. Cancelling the remote request is best effort; a late response from the previous failure epoch cannot mutate current state.

This ordinary/parallel coordination contract is asymmetric: remote work may improve a future target round, but it never acquires authority over emitted tokens, target KV, request completion, or the target-only fallback path.

Remote placement adds metrics absent from a colocated design:

network serialization and transfer latency
remote queue and service time
timeout / stale-result / cancellation rates
native small-model traffic interference
draft reuse and invalidation fraction
target idle time waiting for proposals
Colocated, remote serial, and remote overlapped drafting with deadlines, generation checks, and ordinary decode fallback

0x0C Evaluation Is An Experimental Contract

A throughput number is not evidence unless the treatment, baseline, workload, arrival process, stopping rule, and unit of analysis were fixed before the run. The experiment manifest is immutable and content-addressed:

experiment:
  manifest_version: m7.8-eval-v1
  trace_hash: sha256:...
  split_hash: sha256:...
  target_release_hash: sha256:...
  candidate_release_hash: sha256:...
  request_seed_manifest: sha256:...
  arrival_process: open_loop_trace_replay
  warmup_requests: 500
  measured_requests: 10000
  policies: [target_only, fixed_k_1, fixed_k_3, batch_schedule, adaptive]
  primary_endpoints: [final_output_goodput, p99_tpot, correctness]
  inferential_unit: request
  confidence_level: 0.95
  multiplicity: holm
  stopping: fixed_horizon

The split is made at a dependency-preserving unit such as conversation, repository, tenant trace, or session. Splitting tokens or turns from one conversation between calibration and evaluation leaks proposal difficulty and arrival structure. Controller thresholds, acceptance priors, shape profiles, and graph buckets are frozen before the evaluation split is opened.

0x0CA Correctness Hierarchy Before Performance

Correctness has several non-interchangeable levels:

LevelContractTest
State safetyemitted prefix, target KV, draft KV, RNG, and frontier agreeexecutable invariants after every forced transition
Deterministic equivalencetarget-only and speculative paths emit the same greedy sequence in a controlled backendpaired token equality and first-divergence trace
Distributional equivalencestochastic outputs follow the target distribution under the stated samplerrepeated paired prompts and predeclared two-sample tests
Numerical compatibilitylogits or logprobs stay inside a product toleranceabsolute/relative error by position and batch shape
Operational safetytimeout, preemption, disable, and rollback preserve statefault injection and epoch assertions

Greedy token equality is stronger than necessary for a mathematically exact sampler but useful for integration debugging. Conversely, matching a few greedy outputs does not test stochastic exactness. Current vLLM documentation also warns that floating-point order and batch shape can change observed outputs; the release must name whether its promise is token equality, distributional equivalence, or bounded numerical difference.

Cache cases must include all accepted, reject-first, reject-middle, EOS inside the proposal, correction and bonus frontiers, preemption/resume, K=0 state transitions, stale draft state, tree-sibling rollback, and duplicate remote completion.

0x0CB Paired Replay And The Unit Of Analysis

Replay the same request, seed, arrival timestamp, output cap, and admission class under target-only and candidate policies. For request , define a paired difference for metric :

The estimated treatment effect is:

Its classical paired standard error is:

Tail latencies, controller actions, and requests sharing one arrival trace are not independent Gaussian samples. Use a paired bootstrap over the highest independent unit, usually request clusters, sessions, or whole replay blocks. Report the point estimate and confidence interval, not only the winning mean. Tokens from one request are never thousands of independent observations.

def paired_block_bootstrap(blocks, metric, draws, rng):
    effects = []
    for _ in range(draws):
        sample = rng.choice(blocks, size=len(blocks), replace=True)
        effects.append(mean(
            metric(block.candidate) - metric(block.baseline)
            for block in sample
        ))
    return quantile(effects, [0.025, 0.5, 0.975])

If five policies are compared with one baseline over several primary endpoints, unadjusted multiple comparisons inflate false discoveries. Predeclare the primary family and apply Holm correction or another named procedure. Exploratory segments remain useful, but their intervals are labeled exploratory rather than promoted to release gates after seeing the data.

Sequential dashboards create another trap. Looking every minute and stopping at the first favorable confidence interval invalidates a fixed-horizon test. Use a fixed sample size or a predeclared group-sequential design with alpha spending. A safety stop for corruption or severe SLO regression is always allowed; it is not evidence of efficacy.

0x0CC Workload And Policy Matrix

Cross the dimensions that change proposal quality or physical execution:

arrivals: closed loop, low/medium/near-saturation open loop, burst trace
lengths: short/short, long/short, short/long, long/long
workloads: code, chat, reasoning, retrieval-heavy, deliberate drift
sampling: greedy, temperature and top-p buckets, supported penalties
state: cold prefill, prefix hit, preempt/resume, adapter mix
placement: colocated, remote ordinary, remote parallel where supported
policies: K=0, each supported fixed K, batch schedule, adaptive controller

K=0 is the causal baseline, not merely one candidate in the adaptive policy. Fixed- arms reveal whether an adaptive win comes from control or simply from choosing one generally better depth. A batch-size schedule separates online acceptance adaptation from static shape adaptation.

Ragged batches also require a length-aware baseline. Batch Speculative Decoding Done Right groups or pools requests by compatible progress to reduce padding and synchronization work; such grouping changes the scheduler and must be enabled on both arms when the question is the incremental value of speculation.

Length-aware request pooling for ragged speculative batches

Source: Batch Speculative Decoding Done Right, system illustration. The figure motivates progress-aware grouping; it does not establish that one grouping policy is universally optimal.

0x0CD Metrics, Denominators, And Release Gates

product:
    TTFT, TPOT, end-to-end latency, timeout and error rate

useful service:
    final-output goodput, committed tokens, completed requests

speculation:
    proposals and acceptance by depth, K histogram, K=0 share,
    query rows per committed token, correction/bonus frontier rate

physical cost:
    proposer/transfer/verify/select/sync/repair time,
    temporary and committed KV, graph hits, all-to-all bytes

queueing:
    arrivals, admission delay, active requests, queue depth,
    preemption and stability margin

Every ratio names its denominator. Acceptance is accepted proposal tokens over proposal tokens that were actually eligible at that depth. Final-output goodput excludes rejected rows. Tail latency is computed over completed requests with timeout and cancellation reported separately, not silently dropped.

A conservative release gate can be written:

The thresholds and are product decisions fixed before the run. Statistical significance without a material margin does not justify new runtime state.

Immutable split feeding paired target-only and speculative replays, request-level confidence intervals, multiplicity control, and release gates

0x0D Paper And Runtime Contracts Are Not Interchangeable

WorkPrimary ownerControl variableEvidence suppliedWhat it does not transfer automatically
Leviathan et al.exact one-sequence samplingdraft length in algorithmtarget-distribution-preserving accept/correct ruleshared-server speedup or cache integration
Synergybatching/speculation interactiondraft length by batch regimemeasured optimum changes with batch/model/GPUonline controller or release procedure
TurboSpecclosed-loop serving controldepth including zerooffline cost profile plus online acceptancearbitrary hardware profile reuse
2026 latency modelpre-saturation explanationeffective fixed/marginal costsinterpretable load-latency modelpost-saturation queue dynamics
Batch Done Rightragged batch executionsynchronization and groupingposition/mask/KV realignment contractexact sampler derivation
SPECTREremote multi-tenant proposal serviceordinary/parallel coordinationoverlap and threshold modellocal correctness authority transfer
vLLM / TensorRT-LLMconcrete engine behaviorsupported schedules and methodsimplementation and compatibility surfaceuniversal API or performance guarantees

This table is a paper-by-contract comparison, not a leaderboard. Each source answers a different question. M7.8 composes them only after preserving their assumptions and assigning every state mutation to one runtime owner.

0x0E Release Artifact And Compatibility Contract

The deployable object is a content-addressed bundle, not a target checkpoint plus an informal flag:

speculative_release:
  schema: m7.8-release-v1
  release_id: sha256:...
  parent_release_id: sha256:...
  target:
    checkpoint: sha256:...
    config: sha256:...
    tokenizer: sha256:...
    dtype: bf16
    quantization: none
  proposer:
    method: eagle_or_draft_or_retrieval
    artifact: sha256:...
    feature_or_vocab_mapping: sha256:...
    maximum_topology: {depth: 5, nodes: 5}
  verifier:
    algorithm: rejection_sampling_vX
    sampler_features: [temperature, top_p]
    rng_contract: per_request_counter_v1
  runtime:
    engine_commit: ...
    kernel_build: sha256:...
    driver_and_gpu: ...
    topology: {tp: 1, pp: 1, ep: 1}
    graph_buckets: [0, 1, 3, 5]
  controller:
    profile: sha256:...
    acceptance_schema: v2
    policy: sha256:...
    stability_and_hysteresis: {...}
  evidence:
    immutable_eval_manifest: sha256:...
    correctness_report: sha256:...
    paired_replay_report: sha256:...
    fault_injection_report: sha256:...
  rollback:
    target_only_compatible: true
    prior_release_id: sha256:...

The release ID hashes the canonical manifest payload, excluding the digest field itself and any later operational receipts that refer to it. A profile, acceptance model, or graph bucket cannot be copied into a release whose target, runtime, placement, or physical shape differs.

For speculation inside an M8.10 low-bit deployment, this is a feature-level manifest and evidence boundary, not authority to promote the whole quantized tuple. Freeze the feature manifest, allowed speculative/target-only modes and switching rules in the parent configuration before evaluation. Operational child receipts then bind that frozen parent and feature identity; they are not inserted back into the parent hash. A registered, evaluated same-target disable can remain within . Adding a mode, changing its switching policy or changing the target artifact/representation requires a new tuple and its release gates.

Compatibility checks occur before load and again before request eligibility:

tokenizer/vocabulary and special-token identity
target architecture, dtype, quantization, and parallel ownership
proposal feature layers, output projection, or retrieval-index lineage
sampler features and RNG semantics supported by the verifier
profile hardware, kernel, graph, KV, adapter, and placement identity
temporary KV/workspace reserve and remote protocol version
rollback target-only path tested for this exact bundle

A migration changes one compatibility generation at a time. Existing requests remain pinned to the generation that owns their target KV and RNG state; new requests enter the new generation. Cross-generation proposal results are stale even when request IDs happen to match.

0x0F Canary, Release, And Rollback

Each stage has an entry artifact, an exposure bound, an exit gate, and an automatic abort condition:

StageExposureRequired evidenceExit gate
0 shadowno output mutationprofile residuals, acceptance, memory, numerical deltasshape support and no state mutation
1 deterministicinternal/canary tenantstoken equality, cache and epoch assertionszero correctness failures
2 low loadlow QPS and bounded methodspaired latency/goodput, cold-start costmaterial gain without SLO regression
3 load ramppredeclared QPS stepsqueue stability, dynamic K, memory, tailsgates pass at every measured step
4 drift/faultsynthetic shifts and injected faultstarget-only continuation and evidence preservationall rollback paths close
5 bounded productionsmall traffic fractionlive baseline deltas and failure budgetdwell window passes before expansion

Do not reuse the same canary data to tune thresholds and certify them. A failed stage creates a new candidate release and a new evidence lineage; it does not rewrite the prior report.

0x0FA Rollback Is A State Transition, Not A Cache Clear

ENABLED
  -> DRAINING: stop new speculative rounds; allow owned target work to finish
  -> TARGET_ONLY: materialize visible frontier, discard provisional branches
  -> PROPOSER_QUIESCED: reject remote/local proposals and drain late results
  -> UNLOADED: free draft weights, retrieval index, draft KV, and workspaces
  -> PRIOR_RELEASE: route new requests to the previous compatible bundle

Rollback levels may stop at any safe state. TARGET_ONLY is often enough to restore service without unloading the proposer. No transition discards committed target KV or replays emitted output.

TARGET_ONLY here keeps the same target representation and consumes the registered fallback policy. PRIOR_RELEASE routes new requests; it does not assert that existing target K/V can be attached to a different model or quantized artifact. Existing sessions remain pinned or follow an explicit reconstruction/migration contract admitted by M5.3. Feature rollback cannot replace the M8.10 parent tuple’s quality, resource and operational gates.

def rollback_request_to_target_only(req, failure_epoch):
    assert not req.finished  # continuation path, not terminal cache release
    req.accepting_proposals = False
    cancel_unverified_proposal_work(req)
    discard_uncommitted_target_branches(req)

    if req.pending_frontier_token is not None:
        target_append_frontier(req)

    req.proposal_enabled = False
    req.current_K = 0
    req.failure_epoch = failure_epoch
    req.draft_cache = release_or_quarantine(req.draft_cache)

    assert req.target_cache.token_count == len(req.output)
    assert no_result_from_older_epoch_can_publish(req)

0x0FB Automatic Disable And Causal Evidence

Correctness-unknown state disables immediately. Performance gates use a dwell window and hysteresis unless an absolute SLO or stability boundary is crossed:

correctness:
    cache/position/mask/RNG invariant failure, unsupported sampler,
    unknown proposal provenance, stale generation publication attempt

capacity:
    temporary reserve breach, allocator failure, remote overload,
    MoE straggler/all-to-all limit

performance:
    goodput LCB below target-only margin, TPOT/E2E UCB above SLO,
    stability margin below floor, profile residual outside envelope

readiness:
    missing draft prefill, stale index/cache, graph/profile unsupported

Every trigger writes a causal record:

DisableEvent(
    release_id,
    request_or_server_scope,
    failure_epoch,
    reason_code,
    observed_value,
    threshold,
    profile_generation,
    controller_decision_id,
    state_before,
    state_after,
)

The fallback is fail-closed: unknown profile, cache provenance, proposal state, or verifier support yields K=0. It does not invent a conservative positive depth.

Content-addressed speculative release progressing through evidence-gated canaries and transactional target-only rollback states

0x10 Failure Lab

FailureObservable symptomViolated contractDetectionRecovery
Fixed at high QPSTPOT and queue exceed target-onlyaction ignores physical batch/loadpaired load replay, stability margincontroller chooses supported smaller or zero
Acceptance model mixes code and chatoscillation and biased goodputnonexchangeable traffic pooledresiduals by bucket, probe armsegment, decay, hierarchical fallback
Output outruns target KV without frontiernext round uses wrong positionoutput/KV frontier invariantper-round state assertionmaterialize frontier before further decode
Draft cache retains rejected suffixfuture proposals condition on rejected tokensdraft lineage invarianttoken/hash comparisontruncate and repair or disable proposer
Full acceptance repairs only the bonus in the drafterfinal accepted proposal has no draft KV rowindependent model-cache prefixestrack proposed count and executed draft forwardsprocess the final proposal and bonus before resuming
Finished request re-enters draftingoutput grows after EOS/length capterminal-state authoritystopped-round regressionforbid dispatch; release or explicitly export retained state
Ragged rows use padded positionswrong logits despite plausible shapesposition/mask/KV synchronizationeager oracle and forced heterogeneous acceptsunpad/append/repad or verified custom kernel
Late remote result publishesstale proposal mutates a newer iterationgeneration and failure-epoch authoritystale-result counter/assertiondiscard result; target-only continues
Profile extrapolates through graph cliffpredicted win becomes tail regressionmeasured support contractresidual envelope and shape-key missK=0, quarantine profile, remeasure
Dynamic destroys graph reuselaunch overhead dominatesaction and graph bucket disagreegraph-hit histogramconstrain feasible actions to captured buckets
Tree expansion OOMspreemption cascadetemporary state omitted from admissionpeak allocation and reserve assertionreject action before proposal
Target changes without proposer/profileacceptance and latency collapserelease compatibility generationload-time hash gatereject bundle; build new evidence lineage
Rollback clears committed target KVduplicate or divergent outputpublication transaction brokenoutput/KV prefix auditrestore prior durable state; stop release
Fixed-horizon test stopped earlyapparent positive result does not replicatesequential stopping contractaudit dashboard looks/stopping logrerun predeclared design
Token-level CI is extremely narrowfalse certaintyinferential unit is wrongcompare request/block bootstrapcluster at request/session/trace level
Timeouts excluded from latencycandidate looks artificially fastdenominator/censoring contractcompletion accounting reconciliationreport timeout separately and as product failure

0x11 Operational Dashboard And Evidence Closure

The dashboard connects decisions to user outcomes while retaining immutable raw evidence:

service: QPS, admissions, queue, TTFT, TPOT, E2E, timeouts
policy: feasible-action count, rejection reasons, K distribution, K=0 share
utility: committed output, final-output goodput, baseline delta and CI
acceptance: reached/accepted by depth, segment, proposal and target generation
cost: draft, transfer, verify, sync, repair, graph hit, temporary KV
state: frontier count, rollback level, cache invariant and stale-result failures
placement: remote queue/network/deadline, target wait, ordinary/parallel share

Alerts combine absolute SLOs with target-only deltas. A speculative path can be internally stable yet still be worse than ordinary decoding. Each dashboard point links to the release, profile, controller decision, and failure epoch that produced it.

0x11A Implementation References Are Versioned Evidence

The following references are examples of current implementation surfaces, not portable API promises:

vLLM:
    f57123aa2dbc1badb1865b18c724b308f90dceda

TensorRT-LLM:
    43edf6257bcbf55fb5ad27c3d3162351c2547f32

eBay spec_dec:
    4aa1e3424570f64381975576a71fcf0b18440a06

SGLang:
    bc7e1a07c3ae7733f639ab531fe42c084ed31d84

Pinning a commit makes a claim auditable. It does not imply that all four systems expose identical samplers, cache layouts, dynamic-depth policies, or graph behavior.

0x11B Visual And Source Provenance

Paper figures in this article are reproduced for explanation with source and figure context in their captions. SVGs authored for this program are redrawn semantic diagrams, not paper screenshots. Their editable generation script and manifest live under docs/numinens-evidence/m7-8-speculative-serving-lifecycle/. Formulae labeled as teaching models preserve the cited paper’s assumption boundary; production recommendations are identified as synthesis.

End-to-end speculative serving lifecycle from immutable manifest through synchronized execution, measured control, paired evaluation, release, and rollback

0x12 Red Flags

"Speculative decoding is lossless, so rollout is low risk."
    Algorithmic exactness does not validate cache, batching, RNG, or integration.

"Acceptance rose, therefore serving improved."
    Useful output must be divided by complete service cost under load.

"A latency model chose K, so the shape is supported."
    A model cannot authorize an unprofiled graph, memory, or placement shape.

"K=0 means the draft can resume immediately."
    Not after skipped draft prefill or stale cache lineage.

"Rollback means clear speculative caches."
    Materialize visible frontier and preserve committed target state first.

"Every token is an independent evaluation sample."
    Requests and traces own correlated execution and outcomes.

"One successful canary proves every traffic segment."
    Release claims are bounded by the immutable evaluation support.

0x13 Publish Gate

  • The owner question and M5.2/M7.1/M7.7 boundaries are explicit.
  • Immutable release, request, round, profile, and failure generations exist.
  • The full accepted-prefix distribution and its variance are derived.
  • Ragged position, mask, output, and KV synchronization are executable.
  • Logical output, query rows, temporary state, and committed KV are separate.
  • Profiles declare support, residuals, invalidation, and K=0 fallback.
  • Queue stability and its pre-saturation assumptions are explicit.
  • The controller optimizes a constrained physical action with uncertainty.
  • Cache publication and repair distinguish output, target KV, and draft KV; full/partial/zero acceptance and stopping have explicit ledgers.
  • Colocated and remote ordinary/parallel placement retain target authority.
  • Evaluation uses immutable paired replay, confidence intervals, multiplicity, and a stopping rule.
  • Release and rollback preserve generations, committed state, and causal evidence.
  • Paper claims, runtime observations, and implementation versions are scoped.
  • Formula, source, local-link, asset, desktop, and mobile audits close.

0x14 M7 Completion Boundary

M7 now spans the path from exact algorithm to reversible production system:

M7.1: one-sequence probability and correction contract
M7.2-M7.7: proposal, topology, training, retrieval, and verification choices
M7.8: synchronized service, measured control, evaluation, release, rollback

The deployment conclusion is conditional by design. Speculative decoding is not a property of a checkpoint. It is a joint property of proposal quality, target verification, tensor layout, cache transactions, traffic, scheduling, kernels, placement, and one versioned release artifact. When that joint contract stops holding, target-only decoding remains the ordinary, measurable, and state-preserving continuation.

References

  1. Qidong Su, Christina Giannoula, Gennady Pekhimenko. The Synergy of Speculative Decoding and Batching in Serving Large Language Models.
  2. Xiaoxuan Liu et al. TurboSpec: Closed-loop Speculation Control System for Optimizing LLM Serving Goodput.
  3. Linghao Kong et al. An Interpretable Latency Model for Speculative Decoding in LLM Serving.
  4. Woosuk Kwon et al. Efficient Memory Management for Large Language Model Serving with PagedAttention.
  5. Yaniv Leviathan, Matan Kalman, Yossi Matias. Fast Inference from Transformers via Speculative Decoding.
  6. Ranran Haoran Zhang et al. Batch Speculative Decoding Done Right.
  7. Jincheng Xie et al. SPECTRE: Hybrid Ordinary-Parallel Speculative Serving for Resource-Efficient LLM Inference.
  8. vLLM. Speculative Decoding and Dynamic Speculative Decoding, documentation inspected against commit f57123a.
  9. NVIDIA. TensorRT-LLM Speculative Decoding, implementation inspected against commit 43edf62.
  10. eBay. spec_dec, commit 4aa1e34.
  11. SGLang. Speculative decoding implementation, commit bc7e1a0.
  12. Immi’s Workshop. A30 - Decoding Speculation.
  13. Immi’s Workshop. A31 - Medusa.
  14. Immi’s Workshop. A32 - Lookahead Decoding.
  15. Immi’s Workshop. A33 - DeepSeek MTP.