Skip to main content
Everything in this module centers on one promise: A conversation that comes back shouldn’t pay for its own history. This lesson demonstrates that promise with a five-turn chat. You’ll see how prompt token counts grow while per-turn latency stays stable, thanks to prefix caching.
This demo illustrates prefix caching: previously-seen prompt prefixes are cached so the model doesn’t reprocess them token-by-token on every turn. That keeps repeated conversation turns inexpensive even as the transcript grows.

Concept recap

  • Models are stateless between requests: a typical chat turn resends the entire conversation (opening context, every question, every answer, plus the new question).
  • That transcript grows with each turn, increasing how many tokens the server must read and (without caching) reprocess.
  • Prefix caching prevents that growth from making each subsequent turn more expensive: previously-seen prefixes are cached and do not need reprocessing, only the newest tail requires fresh work.

Conversation setup

  • We start with an opening context deliberately longer than one cache block so the cache will be exercised.
  • Each loop appends a new question to the transcript, builds a JSON payload safely using jq, posts to the local completions endpoint, records timing and prompt token usage, then appends the model’s answer back into the transcript for the next loop.
  • Using jq to construct the JSON payload avoids common demo failures from unescaped quotes, newlines, or other special characters in model output.
Here is the full shell loop used to run five turns. Note how jq is used to build a safe JSON payload from the transcript rather than attempting to hand-glue text into JSON.
Note: Using jq to construct the request ensures proper escaping of any quotes, newlines, or other characters in the model’s answers. This avoids common demo failures caused by hand-gluing untrusted text into JSON.

Example run: single-turn output

Full five-turn run (prompt token counts and timings)

Observations

  • Prompt tokens increase each turn as the transcript grows (143 → 463 in this run).
  • Despite the transcript more than tripling in token count, per-turn latency barely decreases across turns. That indicates the cache is absorbing previously seen content: the server doesn’t re-read the cached prefix token-by-token, only the newest tail needs fresh processing.
  • This behavior yields stable latency for long-lived chats when sessions are routed consistently to pods that hold the cached prefixes.

Validate cache behavior with Prometheus

To confirm cache behavior across the fleet, check the prefix cache hit ratio (hits / queries). As the conversation grows, this ratio should climb toward 1 — meaning most prefix tokens were served from cache. Prometheus query (ratio):
These metrics are exported by vLLM (https://github.com/vllm-project/vllm). Example output:
A rising ratio indicates an increasing share of each prompt was served from cache rather than recomputed. Prometheus query (per-pod increase in cache hits over 5m):
Example per-pod output:
  • The per-pod view shows where sessions are being served from. In this experiment a single pod owned the session; its cache hits increased while other pods showed none.

Quick reference

Summary

  • The test shows that as the conversation grows, most of the transcript becomes cached and subsequent turns do not pay again for the cached history.
  • A router that consistently sends a session back to the same pod plus an effective prefix cache keeps conversation performance stable even as the transcript grows.
  • When fleet memory is limited, precise session routing and tiered storage strategies help maintain cache effectiveness at scale.
Using a safe JSON builder like jq to construct request payloads is important in demos — model-generated text can contain quotes, newlines, and other characters that break hand-built JSON.

Watch Video