Cache Hit-Rate Measurement and Optimization: How to Go From 50% to 85%
You enabled cache but hit-rate is stuck at 50%. This indicates a prompt architecture issue. This lesson covers hit-rate measurement dashboard, miss reason analysis, iterating with A/B tests, and patterns to reach 85%.
Şükrü Yusuf KAYA
18 min read
Advanced📊 Cache açtın, hit oranın az? Bu ders senin için
Production'da cache enable edilen ekiplerin çoğu %50-60 hit-rate ile takılıyor — sandıklarından daha az tasarruf. Bu derste sınırı aşma pattern'lerini görüyoruz.
Önce Ölç — Hit Rate Dashboard'u#
Modül 3'te telemetry kurduk. Cache metric'lerine ekstra dikkat:
Anthropic için#
SELECT toDate(ts) AS day, sum(cache_read_input_tokens) / sum(input_tokens + cache_creation_input_tokens + cache_read_input_tokens) * 100 AS cache_hit_pct, sum(cost_total_usd) AS total_cost, count() AS requests FROM llm_telemetry.requests WHERE provider = 'anthropic' AND ts >= now() - INTERVAL 7 DAY GROUP BY day ORDER BY day
OpenAI için#
SELECT toDate(ts) AS day, sum(cached_input_tokens) / sum(input_tokens) * 100 AS cache_hit_pct, ... FROM llm_telemetry.requests WHERE provider = 'openai' GROUP BY day
Hedef Hit-Rate Aralıkları#
Workload tipine göre realistik hedefler:
| Workload | Realistic hit-rate hedef |
|---|---|
| Statik sistem prompt + dinamik query | %80-90 |
| Multi-tenant (her tenant cache invalid eder) | %60-75 |
| Conversation chatbot (multi-turn) | %85-95 |
| RAG (statik KB + dinamik chunks) | %50-65 |
| Single-shot generation | %0 (cache yararsız) |
Hedef'in altındaysan#
%40-50'de takılıyorsan: prompt mimari problemi.
%60-70: ince ayar gerekli.
%80+: ufak iyileştirmeler.
En Yaygın Cache Miss Sebepleri (Hangisi senin?)#
Sebep 1 — Sistem Prompt'ta Dinamik Veri#
# YANLIŞ SYSTEM = f"User: {user_name}\nDate: {datetime.now()}\n..."
Tespit: Eski-yeni system prompt'larının hash'lerini logla, %100 unique varsa bu hata.
import hashlib sys_hash = hashlib.md5(SYSTEM.encode()).hexdigest() log_metric("system_prompt_hash", sys_hash) # Dashboard'da unique hash sayısı = miss sebebi
Sebep 2 — Tool Order Değişiyor#
# YANLIŞ tools = list(tool_registry.values()) # dict order non-deterministic
Tespit: Her isteğin tool list'inin hash'ini logla.
Sebep 3 — Whitespace Farklı#
# YANLIŞ if user.premium: SYSTEM = "Sen premium destek için asistansın.\n\n" + CORE else: SYSTEM = "Sen normal destek için asistansın.\n\n" + CORE
İki user grubu cache miss yapıyor birbirine.
Çözüm: Tek SYSTEM, premium info'yu user message'a koy.
Sebep 4 — Model Snapshot Auto-Update#
gpt-5gpt-5-2026-02-01Sebep 5 — TTL Süresi Aşıldı#
Anthropic 5dk ephemeral: 5 dakika boyunca istek gelmezse cache temizlenir. Düşük-traffic feature'lar için 1h TTL kullan.
Sebep 6 — Cache Min Size'ı Altında#
Anthropic'te Sonnet için <1024 token, cache eligible değil. Sistem prompt'unu yeterli boyutta tut.
Tanı Akışı#
1. Cache hit-rate < %50 mi? ├── EVET → Diagnostic adımına git └── HAYIR → İdeal pattern, tebrikler 2. System prompt'un hash'i unique mı? ├── EVET → Dinamik veri var, çıkar └── HAYIR → Devam 3. Tools list'in order'ı stabil mi? ├── EVET → Devam └── HAYIR → Alfabetik sırala 4. Model snapshot pinned mi? ├── EVET → Devam └── HAYIR → Pin et 5. Cache eligible boyutta mı (≥1024)? ├── EVET → Devam └── HAYIR → System'i büyült 6. TTL doğru mu (high traffic 5dk, low traffic 1h)? ├── EVET → Marjinal optimizasyon, %75+ targetladık └── HAYIR → Ayarla
Iterate Pattern — A/B Test ile Cache Optimizasyonu#
Cache mimarini değiştirdin. Şimdi doğrulamak için:
# Variant A: eski mimari def chat_v1(query): return anthropic.messages.create( model="claude-sonnet-4-6", system=OLD_SYSTEM_PROMPT, # cache_control yok messages=[{"role": "user", "content": query}], ) # Variant B: yeni mimari with cache def chat_v2(query): return anthropic.messages.create( model="claude-sonnet-4-6", system=[ {"type": "text", "text": NEW_SYSTEM_STATIC, "cache_control": {"type": "ephemeral"}}, ], messages=[{"role": "user", "content": query}], ) # A/B feature flag def chat(query, user_id): variant = "v2" if hash_user(user_id) % 2 == 0 else "v1" response = (chat_v1 if variant == "v1" else chat_v2)(query) log_metric(f"cache_hit_pct_{variant}", calc_hit_pct(response)) log_metric(f"cost_per_request_{variant}", calc_cost(response))
48 saatlik test sonrası dashboard:
| Variant | Cache hit % | Avg cost/req |
|---|---|---|
| v1 (no cache) | 0% | $0.024 |
| v2 (cache) | 83% | $0.0085 |
%65 cost düşüş. Ship v2.
İleri Teknik — Cache Warmup#
Yeni deploy sonrası cache boş. İlk istekler maliyet bombası.
Solution: Active warmup#
Deploy sonrası proactive isteklerle cache'i ısıt:
async def warmup_cache(): """Deploy sonrası cache'i hazırla.""" warmup_queries = [ "Hello", # küçük dummy query "Hi", "Test", ] for q in warmup_queries: await anthropic.messages.create( model="claude-sonnet-4-6", system=[ {"type": "text", "text": SYSTEM_STATIC, "cache_control": {"type": "ephemeral"}}, ], messages=[{"role": "user", "content": q}], max_tokens=10, ) # Deploy hook # kubectl apply ... && python warmup.py
3 dummy istek = $0.10 maliyet, sonrası tüm production trafiği cache hit. 2-3 dakika içinde geri öder.
Scheduled warmup (low-traffic features için)#
# Cron: her 4 dakikada warmup query # Cache TTL 5dk olduğundan, hiç soğumaz
Bu pattern, low-traffic agent'lar için kritik.
Multi-Tenant'ta Cache — Özel Senaryolar#
Her tenant kendi konfigürasyonu ile gelir. Cache mimari:
Option A — Tek shared cache (en yüksek hit-rate ama az personalization)#
# Tüm tenant'lar aynı system prompt SYSTEM = GENERIC_SYSTEM # tenant config user message'a
✅ %90+ hit-rate
❌ Tenant-spesifik tone/branding zor
Option B — Tenant-aware cache (orta hit-rate, full personalization)#
# Tenant prompt'u system'da SYSTEM = f"{tenant.system_prompt}\n\n{COMMON_KB}"
✅ Per-tenant cache hit pattern
❌ Tenant sayısı kadar farklı cache; her cache'in TTL'i ayrı
Option C — Hybrid (en yaygın)#
messages = [ { "role": "system", "content": [ # Common — yüksek cache hit {"type": "text", "text": COMMON_SYSTEM, "cache_control": {"type": "ephemeral"}}, # Tenant-spesifik — per-tenant cache {"type": "text", "text": tenant.config, "cache_control": {"type": "ephemeral"}}, ], }, {"role": "user", "content": query}, ]
Multi-layer caching ile her ikisinden de avantaj.
▶️ Sıradaki ders
7.6 — Cache Invalidation: Tools, System Message, FAQ Verisi Güncellenirken. Cache açıldıktan sonra, bir gün system prompt'u güncellemen lazım. Bunu nasıl yaparsın stale cache'siz, dual-write pattern, ve aşamalı rollout.
Frequently Asked Questions
Yes — Langfuse parses the usage object automatically; dashboards like cache_read_tokens / total_input are available by default. You can extend with custom panels.
Yorumlar & Soru-Cevap
(0)Yorum yazmak için giriş yap.
Yorumlar yükleniyor...
Related Content
Module 0: Why Cost, Why Now?
The AI Cost Explosion: Why Token Prices Fell 96% from 2022 to 2026 — Yet Bills Grew 40×
Start LearningModule 0: Why Cost, Why Now?
Unit Economics Vocabulary: COGS, Gross Margin, $/User, Contribution Margin — 9 Financial Concepts Every AI Engineer Must Know
Start LearningModule 0: Why Cost, Why Now?