Skip to content

Move a finished conversation's prefix cache to disk - #2261

Open
Lazarus-931 wants to merge 2 commits into
Blaizzy:mainfrom
Lazarus-931:feat/cache-offload-v2
Open

Lazarus-931 wants to merge 2 commits into
Blaizzy:mainfrom
Lazarus-931:feat/cache-offload-v2

Conversation

@Lazarus-931

@Lazarus-931 Lazarus-931 commented Sep 15, 2026

Copy link
Copy Markdown
Collaborator

Free the memory a finished conversation's prefix cache is holding, without losing the cache.

When a conversation goes idle, its KV cache just sits in memory. POST /v1/cache/offload writes that prefix to disk, waits for the write to land, then releases the memory. A later request with the same prefix still reuses it from disk instead of re-prefilling from scratch.

A block is only released once it is on disk and no in-flight request is still holding it. Anything that fails either check stays in memory and is reported back as retained, so the endpoint can never pull a cache out from under a running request.

You hand it the conversation the same way you'd hand it to /v1/responses.

Testing

Ran it against 110 checkpoints spanning 40 model families.

Every one freed its memory and handed every block back to the pool — nothing leaked, and the prefix was still reusable afterwards. A typical conversation freed about 110 MB, the largest 660 MB. Most calls finished in under 3 seconds.

One thing worth flagging so it doesn't look like a bug: about a dozen of those families never report cached_tokens in usage, even on an ordinary warm hit with no offload involved. On those models the reuse shows up as lower latency rather than in the usage field.

follows #2260

A conversation that has stopped growing still holds the memory its prefix
cache needed while it was live. POST /v1/cache/offload writes that prefix to
disk, waits for the write, and then releases the memory, so the cache stays
available to any later request whose prefix still matches.

The conversation is supplied the way a Responses request supplies it, and the
prefix is taken from the ids generation actually ran over rather than by
re-tokenizing the rendered prompt, which shifts by one whenever a template
emits its own BOS.

A block is released only once it is on disk and no request is still holding
it; anything else stays resident and is reported as retained. Conversations
whose cache is kept as a whole-prefix snapshot rather than blocks are spilled
the same way, since several model families never occupy the block pool. The
salt is recovered from what the manager has stored, because it folds in the
model and processor and is never zero.
@Lazarus-931
Lazarus-931 marked this pull request as draft September 15, 2026 13:19
@Lazarus-931
Lazarus-931 marked this pull request as ready for review September 16, 2026 14:08

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant