Prompt caching: как срезать 80% стоимости LLM-приложения
Самая дешёвая оптимизация LLM-приложения — не смена модели и не RAG, а правильно устроенный prefix cache. Разбираемся, как устроен кэш на самом деле, где ставить точки разрыва, почему порядок сегментов важнее содержания и как мерить hit-rate, чтобы не обманывать себя.
СреднийDevOps с AI25 минAnthropic API, OpenAI API
1
Боль, о которой вы не думали до прода
Пока вы строите агента, цена кажется ерундой: десять центов за прогон. Потом агент уходит в прод — и счёт из API приходит как аренда сервера. Причина чаще не в объёме вызовов, а в префиксе: на каждом вызове вы шлёте один и тот же системный промпт, инструкции, примеры, иногда всю базу знаний.
Prefix caching решает это не так, как кажется. Это не «запомнить ответ на повторяющийся вопрос». Это «запомнить уже обработанный префикс, чтобы не пересчитывать его заново». Claude видит знакомое начало, пропускает самую дорогую операцию — prefill — и начинает с динамической части. Скидка на закэшированные токены: до 90%.
💸 Без кэша
- Prefill 5000 токенов на каждый вызов
- Latency: высокая, одинаковая всегда
- Cost: ×1 (базовая цена за токен)
⚡ С prefix cache
- Prefill считается один раз, потом hit
- Latency на hit: −50% time-to-first-token
- Cost: ×0.1 на закэшированный префикс
Не включайте кэш «на потом». Включайте с первого прототипа — и вы сразу начнёте писать промпты так, чтобы стабильное было сверху. Переделывать структуру промпта под кэш позже — отдельный проект на день.
2
Физика кэша: порядок важнее содержания
Чтобы пользоваться кэшем правильно, держите в голове одну вещь: кэшируется именно префикс, а не фрагмент. Изменился первый символ — весь кэш потерян. Изменилось что-то в середине — всё от этой точки и дальше перестаёт быть кэшированным.
При каждом запросе система ищет самый длинный общий префикс с уже кэшированным. Нашла 4000 токенов совпадения — они идут по цене cache hit (обычно 10% от базовой). Остальное пересчитывается с нуля.
Почему так устроено? Кэшируется не текст, а KV-cache самой модели — внутреннее состояние после прогона префикса через attention. Это состояние зависит от каждого предыдущего токена, поэтому изменение одного символа в начале делает весь кэш невалидным.
Отсюда правило, которое экономит больше всех остальных: тот же самый текст, но переставленный местами, может дать либо 90% скидку, либо ноль. Добавили timestamp в первую строку — hit-rate улетел в пол. Поменяли «You are helpful» на «You are a helpful» — то же самое.
промпт = [система][инструменты][контекст][история][вход]
cache_lookup(промпт):
ищет longest_common_prefix с prev_cached
если hit = [система][инструменты] → скидка на 3000 токенов
если hit = ничего → платишь полную цену за всё
ключевое: hit ищется СТРОГО с начала, префиксноОдно маленькое изменение в системном промпте — и кэш всех ваших клиентов сбросился одновременно. В проде не меняйте промпт «на лету», оформляйте через релиз — и ждите временной просадки hit-rate.
3
Стабильное сверху, динамическое снизу
Самая частая ошибка — сунуть динамический контекст перед стабильным. «User: привет, вот данные о заказе, а теперь отвечай согласно следующим правилам…» — правила оказались ПОСЛЕ данных заказа. Каждый запрос меняет данные — значит, сбрасывается кэш и для правил.
Правильный порядок — по убыванию стабильности. Сверху то, что меняется раз в месяц (system prompt, персона, правила). Ниже — раз в день (инструменты, примеры). Ниже — контекст сессии. В самом низу — то, что меняется каждый запрос: последнее сообщение пользователя.
Звучит просто, но почти каждый первый черновик промпта устроен наоборот. Переверните его — и hit-rate сам поднимется.
❌ Плохо: динамика сверху
- user question
- RAG context
- system rules
- examples
- hit-rate: ~0%
✅ Хорошо: стабильное сверху
- system rules
- tools + examples
- RAG context
- dialogue history
- user question → hit-rate >80%
RAG-контекст — самый коварный слой. Он стабильнее, чем пользовательский ввод, но менее стабильный, чем система. Разместите его посередине с отдельной точкой кэша перед ним — и получите скидку даже на редко повторяющиеся запросы.
4
cache_control: три точки, не больше
Провайдеры дают явный контроль: вы сами ставите точки «до сюда кэшируй». У Anthropic это маркер `cache_control`, у OpenAI — автоматически после 1024 токенов префикса. У Anthropic до четырёх точек, каждая создаёт отдельный кэш-префикс.
Правило трёх точек: первая после системного промпта, вторая после определений инструментов, третья перед RAG-контекстом. Больше точек не дают больше скидки — только усложняют отладку.
TTL — отдельное решение. По умолчанию у Anthropic 5 минут: дёшево записать, быстро истекает. Расширенный TTL на 1 час дороже за запись, но окупается, если запросы приходят реже раза в пять минут. Сначала считайте паттерны, потом включайте длинный.
System prompt
← cache_control #1
Инструменты + базовые инструкции
← cache_control #2
RAG context / знания
← cache_control #3
История диалога + текущее сообщение
не кэшируется — динамическая часть
messages = [
{ role: "system", content: [...], cache_control: "ephemeral" }, // #1
{ role: "user", content: tools_def, cache_control: "ephemeral" }, // #2
{ role: "user", content: rag_ctx, cache_control: "ephemeral" }, // #3
{ role: "user", content: user_message } // dynamic
]TTL на 1 час выгоден, когда ваш p50-интервал между запросами больше 5 минут. Если пользователи спамят подряд — достаточно дефолтных 5 минут, и вы сэкономите на плате за запись.
5
Hit-rate — метрика, о которой все забывают
Вы включили кэш. Счёт уменьшился. Готово? Нет — пока вы не посмотрели на hit-rate. Включить кэш и не попадать в него — обычная история. Провайдер возвращает в каждом ответе три числа: токены из кэша, свежие, записанные. Смотрите на отношение.
Зелёная зона — hit-rate выше 70% на стабильных эндпойнтах. Жёлтая (30–70%) — проверяйте порядок сегментов и ищите динамические куски в середине префикса. Красная (<30%) — кэш не работает вообще: либо TTL слишком короткий, либо что-то сбивает префикс. Без мониторинга вы не поймёте, работает ли оптимизация, пока не придёт следующий счёт.
Где кэш реально экономит?
Стабильный system prompt + меняющиеся сообщения
Общий RAG-контекст между пользователями
Long-running чат-сессии с накапливающейся историей
Уникальный длинный документ на каждом запросе
Редкие запросы раз в час при TTL 5 минут
Если hit-rate внезапно упал — первое, что проверить: не добавил ли кто-то timestamp или случайный ID в системный промпт. Одна невинная строка `generated_at: 2026-04-10T14:32:01` убивает весь кэш.
Результат
Промпт, который кэшируется с первого вызова: стабильное сверху, динамическое снизу, три точки cache_control в нужных местах, hit-rate выше 70% и счёт из API, уменьшившийся в 5–10 раз — без единой строчки оптимизации самой модели.