# KV cache quantization in llama.cpp and vLLM

[Skip to content](#lm-inhoud)Network/[NL](/en/kv-cache-kwantisatie-instellen-in-llama-cpp-en-vllm)EN[Hubhub.llmnet.nlCompare models on task, language, cost and license.](https://hub.llmnet.nl/en/)[Communitycommunity.llmnet.nlPrompt techniques, patterns and system prompts.](https://community.llmnet.nl/en/)[APIapi.llmnet.nlLLMs in production: rate limits, routing, structured output.](https://api.llmnet.nl/en/)[Consultancyconsultancy.llmnet.nlRolling out AI in an organization, pilot to production.](https://consultancy.llmnet.nl/en/)[Newsnieuws.llmnet.nlAI developments, explained for the Netherlands.](https://nieuws.llmnet.nl/en/)[Benchmarkbenchmark.llmnet.nlMeasure AI quality yourself, on your own tasks.](https://benchmark.llmnet.nl/en/)[Careersvacatures.llmnet.nlAI roles, salaries and career paths in the Netherlands.](https://vacatures.llmnet.nl/en/)[Learnleren.llmnet.nlAI concepts in plain language, beginner to builder.](https://leren.llmnet.nl/en/)[Guidegids.llmnet.nlRun AI privately on your own Mac, PC, NAS or home server.](https://gids.llmnet.nl/en/)[Directorydirectory.llmnet.nlMapping the AI ecosystem: tools, models, companies.](https://directory.llmnet.nl/en/)[Radarradar.llmnet.nlSignals from X, research and communities for indie developers.](https://radar.llmnet.nl/en/)[Appsapps.llmnet.nlReviews of AI apps and open-source repos, with tips for builders.](https://apps.llmnet.nl/en/)[llmnet.nl — main site](https://llmnet.nl/en/)[](https://x.com/intent/post?url=https%3A%2F%2Fgids.llmnet.nl%2Fen%2Fkv-cache-kwantisatie-instellen-in-llama-cpp-en-vllm&text=KV%20cache%20quantization%20in%20llama.cpp%20and%20vLLM)[](https://www.linkedin.com/sharing/share-offsite/?url=https%3A%2F%2Fgids.llmnet.nl%2Fen%2Fkv-cache-kwantisatie-instellen-in-llama-cpp-en-vllm)[](https://www.reddit.com/submit?url=https%3A%2F%2Fgids.llmnet.nl%2Fen%2Fkv-cache-kwantisatie-instellen-in-llama-cpp-en-vllm&title=KV%20cache%20quantization%20in%20llama.cpp%20and%20vLLM)[](#)[](https://x.com/intent/post?url=https%3A%2F%2Fgids.llmnet.nl%2Fen%2Fkv-cache-kwantisatie-instellen-in-llama-cpp-en-vllm&text=KV%20cache%20quantization%20in%20llama.cpp%20and%20vLLM)[](https://www.linkedin.com/sharing/share-offsite/?url=https%3A%2F%2Fgids.llmnet.nl%2Fen%2Fkv-cache-kwantisatie-instellen-in-llama-cpp-en-vllm)[](https://www.reddit.com/submit?url=https%3A%2F%2Fgids.llmnet.nl%2Fen%2Fkv-cache-kwantisatie-instellen-in-llama-cpp-en-vllm&title=KV%20cache%20quantization%20in%20llama.cpp%20and%20vLLM)[](#)

 
# Setting up KV cache quantization in llama.cpp and vLLM

 
 Place in the route: Step 2 (Hardware, performance & energy) within the track choosing → installing → using → connecting → managing/serving. If you want to check in advance whether your graphics card is adequate for running modern models, first consult the overview of [what hardware you need to run LLMs locally](https://gids.llmnet.nl/en/hardware-voor-lokale-llm).

 Scope & hardware indication: This guide targets systems with dedicated GPUs (such as Nvidia GeForce, RTX or datacenter accelerators) and modern multi-core processors where available video memory is a limiting factor for long context sequences.

 By Ivo Donker — compiled with AI assistance (Claude & Gemini)

 

 When we deploy local language models to process long documents, deep coding tasks or intensive multi-step conversations, we run into a physical memory barrier almost immediately. Where the static weight of the model rests permanently in graphics memory (VRAM), the key-value (KV) cache grows dynamically with every token supplied and generated. With context windows of 32k, 64k or even 128k tokens, the memory footprint of this cache often exceeds the total size of the base model itself. Anyone wanting to maximize context space without immediately investing in extra graphics cards ends up compressing these temporary attention vectors through quantization.

 In this article we walk through the exact runtime flags and configuration parameters for KV cache quantization in both llama.cpp and vLLM. We cover how FP8, INT8 and INT4 precision work, analyze the trade-offs between memory gains and computational degradation, and explain the effect on language ability. To understand the theoretical foundations of weight compression and bit reduction, [the overview article on quantization](https://gids.llmnet.nl/en/kwantisatie-uitgelegd) covers the underlying principles of rounding, scaling factors and matrix transformations.

 
## Why the KV cache grows linearly with context length

 In autoregressive transformers, the model has to look back at every generated step to all preceding tokens in the active sequence. To avoid recomputing earlier matrix multiplications for key and value pairs at every new token, the inference engine stores these intermediate results per attention layer in VRAM. For an in-depth understanding of how these mechanisms work mathematically, [the explanation of KV caching in transformer architectures](https://leren.llmnet.nl/en/kv-caching-opbouw) sets out exactly how keys and values are structured and stored per attention layer.

 The default precision for this cache has traditionally been 16-bit floating point (FP16 or BF16), which amounts to 2 bytes per element. The theoretical formula for memory usage per token is as follows:

 Geheugen per token (bytes) = 2 * n_layers * n_kv_heads * head_dim * bytes_per_element

 As an illustrative worked example, take a model with 32 layers, 8 KV heads (through Grouped-Query Attention) and a head dimension of 128 (as is common in modern 8B architectures). In FP16, every token in the cache costs: 2 * 32 * 8 * 128 * 2 = 131.072 bytes, that is, exactly 128 KB. At a context of 4,096 tokens this requires roughly 512 MB of VRAM. As soon as we push the context to 128,000 tokens, however, the KV cache alone swallows a full 16 GB of VRAM. Add the roughly 5 to 6 GB of VRAM for a 4-bit quantized 8B base model and a 24 GB consumer card is nearly full for just one active session.

 
 
 
 
 Model architecture (illustrative) | 
 Context length | 
 FP16 cache (2 bytes) | 
 FP8 / Q8_0 cache (1 byte) | 
 Q4_0 cache (~0.55 byte) | 
 

 
 
 
 8B model (32 layers, 8 KV heads) | 
 32,768 tokens | 
 4.00 GB | 
 2.00 GB | 
 1.12 GB | 
 

 
 8B model (32 layers, 8 KV heads) | 
 131,072 tokens | 
 16.00 GB | 
 8.00 GB | 
 4.50 GB | 
 

 
 14B model (48 layers, 8 KV heads) | 
 32,768 tokens | 
 6.00 GB | 
 3.00 GB | 
 1.70 GB | 
 

 
 14B model (48 layers, 8 KV heads) | 
 131,072 tokens | 
 24.00 GB | 
 12.00 GB | 
 6.80 GB | 
 

 
 
 

 To work out how these parameters land for specific model configurations and hardware, the [VRAM calculator for local models](https://gids.llmnet.nl/en/vram-rekenhulp-hoeveel-geheugen-heeft-welk-model-nodig) offers a systematic method for estimating memory limits in advance. In addition, the [interactive KV cache calculator](https://leren.llmnet.nl/en/tool-kv-cache-calculator) lets you vary context lengths, batch sizes and precision levels dynamically to compute exact allocations.

 
## Quantization types for the KV cache: FP8, INT8 and INT4

 Compressing the KV cache differs fundamentally from quantizing model weights. Model weights are static and can be carefully optimized in advance using calibration datasets (as with AWQ, GPTQ or GGUF k-quants). The KV cache, by contrast, arises dynamically while text is being generated. Quantization therefore has to happen on the fly during inference, with minimal computational delay.

 In practice we distinguish three common formats for cache compression:

 
 
- FP8 (E4M3 and E5M2): Uses 8-bit floating-point numbers. The E4M3 format (1 sign bit, 4 exponent bits, 3 mantissa bits) offers excellent dynamic range for activation vectors and comes very close to FP16 quality. It halves memory usage straight to 1 byte per element and is hardware-accelerated on modern GPU architectures.
 
- INT8 (Q8_0 in llama.cpp): Quantizes numbers uniformly to 8-bit integers with a scaling factor per block (often per 32 values). This format works universally on virtually all compute hardware and shows extremely little loss of numerical precision.
 
- INT4 (Q4_0 in llama.cpp): Reduces vectors to 4-bit integers (roughly 0.55 byte per element including scaling factors). This yields a memory saving of about 70% relative to FP16, but can cause slight quality degradation on tasks that demand extreme context precision across long distances.
 

 
## Setting up KV cache quantization in llama.cpp

 Within the ecosystem of llama.cpp (and derived wrappers), two specific parameters control the format of the cache: --cache-type-k (for the keys) and --cache-type-v (for the values). By default, llama.cpp allocates f16 for both buffers.

 Key vectors determine the attention distribution through the inner product with the query vector, while value vectors carry the actual content representations. Because key vectors are more sensitive to quantization noise than value vectors, you can choose an asymmetric configuration (for example Q8_0 for K and Q4_0 for V) when maximum memory savings are necessary.

 The example below shows the startup command for llama-server with a symmetric Q8_0 cache and a context of 65,536 tokens:

 llama-server \
 -m models/Meta-Llama-3.1-8B-Instruct-Q4_K_M.gguf \
 -c 65536 \
 -ngl 99 \
 --cache-type-k q8_0 \
 --cache-type-v q8_0 \
 --host 0.0.0.0 \
 --port 8080

 When you want to use maximum context capacity on a graphics card with limited VRAM (such as 16 GB), a 4-bit configuration can be set for both keys and values:

 llama-server \
 -m models/Meta-Llama-3.1-8B-Instruct-Q4_K_M.gguf \
 -c 65536 \
 -ngl 99 \
 --cache-type-k q4_0 \
 --cache-type-v q4_0 \
 --host 0.0.0.0 \
 --port 8080

 For further guidance on distributing buffers and preventing memory fragmentation, the guide on [optimizing the context window locally](https://gids.llmnet.nl/en/context-window-optimaliseren-lokaal) describes how to set context lengths and buffer space in balance.

 
## Configuration in vLLM for high throughput and an FP8 cache

 Where llama.cpp is optimized mainly for local single use, vLLM targets servers with high processing capacity and multiple concurrent requests. vLLM uses PagedAttention, which divides KV memory into virtual memory pages to counter internal and external fragmentation.

 vLLM supports FP8 KV cache quantization through runtime arguments. On architectures with native FP8 Tensor Cores (such as modern datacenter and consumer chips) this delivers direct hardware acceleration. On older generations the engine can fall back to software conversion, which preserves the memory saving but requires extra instruction cycles.

 To start a vLLM server with an FP8-quantized cache, activate the flag --kv-cache-dtype fp8:

 python3 -m vllm.entrypoints.openai.api_server \
 --model meta-llama/Meta-Llama-3.1-8B-Instruct \
 --kv-cache-dtype fp8 \
 --max-model-len 32768 \
 --gpu-memory-utilization 0.95 \
 --port 8000

 For in-depth instructions on multi-GPU setups, scheduling and server optimization, consult the extensive guide on [configuring a vLLM server on Linux](https://gids.llmnet.nl/en/vllm-server-configureren). If you are unsure which engine suits a specific server setup, [the comparison of vLLM and Ollama for production environments](https://radar.llmnet.nl/en/review-vllm-versus-ollama-voor-productie-op-eigen-servers) offers a systematic evaluation of memory management and throughput under concurrent load.

 Within vLLM, FP8 not only halves the memory footprint per token but also increases the effective capacity of the PagedAttention pool. This lets the system hold substantially more concurrent sessions in video memory before requests have to be swapped to slower system RAM.

 
## Effect on language consistency and quality trade-offs

 An important aspect of cache compression is its potential effect on semantic consistency across long text sequences. Unlike model weights, where quantization noise is distributed globally, noise in the KV cache directly affects the attention distribution between distant tokens.

 In academic literature and general benchmarks, 8-bit variants (FP8 and INT8) typically show a negligible deviation in perplexity relative to FP16. With 4-bit quantization (such as Q4_0), very long sequences (above 32k tokens) can show subtle deviations on tasks that require strict syntax, such as formal logic or retrieving exact facts from large text documents.

 When formulating complex Dutch instructions — where bracket constructions and longer dependencies between verbs and subjects occur — 8-bit quantization keeps working robustly. To check whether the model's responses stay natural and syntactically correct, the article on [optimizing AI performance in Dutch](https://gids.llmnet.nl/en/beter-nederlands) offers useful techniques for consistent output quality.

 
## Impact on throughput: latency and prefill

 Compressing the KV cache affects two phases of the inference process: the prefill phase (processing the initial prompt) and the decode phase (generating new tokens).

 During the prefill phase, the computed activation vectors have to be converted to the lower precision format before they are stored. This requires a small amount of extra compute. During the subsequent decode phase, memory bandwidth between the GPU cores and VRAM is almost always the primary bottleneck. Because 8-bit and 4-bit formats require considerably less data per token to travel across the memory bus, generation speed can actually increase with large contexts.

 The real gain in tokens per second depends heavily on the ratio between context length and GPU compute power: with short prompts (below 2,048 tokens) the effect on speed is minimal, while with long documents the reduction in memory traffic can deliver a clear speed-up.

 
## Troubleshooting and preventing out-of-memory situations

 Even with a compressed cache, runtime interruptions can occur when context space fills up unexpectedly. A common cause in llama.cpp is allocating a context size that fits within theoretical VRAM space but does not account for temporary CUDA compute buffers needed during peak load.

 When a process stops unexpectedly through lack of memory, this can often be traced to an overestimate of available free VRAM or too high a number of concurrent slots. Should the inference engine hang or refuse to start, the troubleshooting guide on [resolving out-of-memory messages and slow inference](https://gids.llmnet.nl/en/als-het-niet-werkt-out-of-memory-trage-tokens-en-een-gpu-die-niet-meed) offers concrete steps for locating memory conflicts step by step.

 
## Privacy and local data processing

 Quantizing the KV cache is a purely mathematical memory optimization that takes place entirely within the local working memory and VRAM of your own system. No intermediate activation layers, embeddings or prompt data are sent to external servers during this process. All context information stays strictly bound to the local machine.

 For organizations deploying local language models to comply with strict privacy guidelines, the overview of [working with local AI in a privacy-friendly way](https://gids.llmnet.nl/en/privacyvriendelijk-ai) describes how data flows can be isolated and managed in line with regulations.

 
## Practical configuration guidelines

 When setting up a local inference environment, the following guidelines apply:

 
 
- Modern GPUs with hardware FP8 support: Preferably use FP8 in vLLM (--kv-cache-dtype fp8) or Q8_0 in llama.cpp (--cache-type-k q8_0 --cache-type-v q8_0). This halves the memory footprint of the cache while preserving numerical stability.
 
- Systems with older GPU architectures or CPU inference: Choose q8_0 in llama.cpp for a balanced trade-off between memory gains and compatibility. Avoid FP8 in vLLM if the GPU offers no native support and compute speed is the priority.
 
- Maximum context capacity on tight hardware: Apply a 4-bit configuration (such as --cache-type-k q4_0 --cache-type-v q4_0 in llama.cpp) when long documents absolutely have to fit within a single graphics card, and spot-check whether output stays consistent on large-scale prompts.
