Bir LLM özelliğinin bütçeyi aşmasının nedeni nadiren modelin pahalı olmasıdır. Fatura, kimsenin saymadığı tokenlerle büyür: her turda yeniden gönderilen konuşma geçmişi, üç parçanın yeteceği yerde on RAG parçası, her çağrıya eklenen araç şemaları, yeniden denemeler, gecelik değerlendirmeler ve yanıtta hiç görünmeyen akıl yürütme tokenleri. Bu rehberde LLM API maliyetini lansmandan önce nasıl tahmin edeceğinizi, sonrasında nasıl ölçeceğinizi ve kaliteden ödün vermeden nasıl düşüreceğinizi anlatıyoruz.
Yazıda bilerek fiyat tablosu yok: fiyatlar sık değişiyor; modele, hizmet katmanına, önbellek ömrüne, prompt uzunluğuna ve bölgeye göre farklılaşıyor. Güncel rakamları OpenAI, Anthropic ve Google Gemini'nin resmi fiyat sayfalarından alıp aşağıdaki formüllere koyun. Sağlayıcı ayrıntılarını Ekim 2026'da resmi dokümantasyondan kontrol ettik; hepsi sağlayıcıya ve modele özgüdür, zamanla da değişecektir.
LLM API faturası nasıl oluşur?
- Girdi ve çıktı tokenleri ayrı fiyatlanır. İncelediğimiz fiyat listelerinde bir çıktı tokeni, bir girdi tokeninden kabaca 4 ila 8 kat daha pahalı. Yine de büyük kalem çoğu zaman girdidir: aşağıdaki örnekte her çağrı, aldığından yaklaşık 20 kat daha fazla token gönderiyor.
- Akıl yürütme (reasoning) tokenleri çıktı olarak faturalanır: OpenAI'ın reasoning modellerinde, düşünme (thinking) özelliği açık Claude'da ve Gemini'nin thinking modellerinde, yanıtta yalnızca bir özet görünse bile. Bu tokenleri metinde değil, usage nesnesinde görürsünüz.
- Önbellekten okunan girdinin kendi fiyatı vardır: okuma ucuzdur, bazı sağlayıcılar ise önbelleğe yazma için ek ücret alır.
- Gönderdiğiniz her şey, her çağrıda girdidir: sistem prompt'u, araç şemaları, örnekler, RAG bağlamı ve konuşma geçmişi. Anthropic, araç tanımlanan her isteğe birkaç yüz tokenlik gizli bir araç kullanım prompt'u da ekler.
- Görseller de tokene çevrilir: Claude görseli 28×28 piksellik parçalarla sayar, yani 1000×1000 piksellik bir görsel 1.296 token eder. Gemini'nin token rehberi küçük bir görseli 258 token sayıp büyükleri karolara böler; Gemini 3 modellerinde ise görsel başına token bütçesini media_resolution parametresi belirler (varsayılan yaklaşık 1.120, low ayarında 280 token).
- Çarpanlar üst üste biner: batch ve flex katmanları daha ucuz, hızlı katmanlar daha pahalıdır; bazı modeller prompt belirli bir uzunluğu aşınca birim fiyatı yükseltir (bazı OpenAI modellerinde 272 bin, bazı Gemini modellerinde 200 bin, Claude Haiku 5.5'te 100 bin token); OpenAI ve Anthropic yeni modellerde bölgesel ya da yalnızca ABD'de işleme için %10 ek ücret uygular; web araması gibi sunucu tarafı araçlar da tokenlerine ek olarak çağrı ya da oturum başına ücretlendirilir.
Hız sınırları (rate limits) ayrı bir alt forumun konusu; bu rehber yalnızca maliyete odaklanıyor.
Tokenizer'lar farklıdır: Türkçe metni ölçün
Tokenizer'lar sağlayıcıya, hatta model kuşağına göre değişir: Anthropic, Claude 4.7 ve sonraki modellerin aynı metin için öncekilerden yaklaşık %30 daha fazla token ürettiğini belirtiyor. Dil de belirleyici. Aynı içeriği taşıyan iki Türkçe-İngilizce metin çiftini (bir müşteri mesajı ve bir destek asistanının sistem prompt'u) OpenAI'ın açık kaynak tiktoken kütüphanesiyle saydık:| Kodlama (encoding) | Türkçe kelime başına token | İngilizce kelime başına token | Aynı içerikte Türkçe ÷ İngilizce token |
|---|---|---|---|
| o200k_base (tiktoken'a göre GPT-4o, GPT-4.1, GPT-5) | 2,06–2,18 | 1,13–1,14 | 1,29–1,31 |
| cl100k_base (GPT-4 ve GPT-3.5 dönemi) | 2,79–3,11 | 1,14–1,15 | 1,76–1,83 |
Sondan eklemeli bir dil olan Türkçede kelimeler uzun olduğu için kelime başına yaklaşık iki kat token gerekir. Aynı içerik için fark ise yeni kodlamada yaklaşık %30'dur, çünkü aynı mesaj Türkçede daha az kelimeyle yazılır; faturaya yansıyan oran budur. İki örnek bir kıyaslama (benchmark) sayılmaz: kendi prompt'larınızı kullanacağınız modelle sayın. Bunun için OpenAI'ın girdi token sayma uç noktası, Anthropic'in ücretsiz count_tokens uç noktası ve Gemini'nin countTokens yöntemi var.
Usage alanlarını doğru okumak
Alanlar sağlayıcıdan sağlayıcıya farklı anlam taşır; karıştırırsanız önbellekten okunan tokenleri iki kez sayarsınız:| Sağlayıcı ve API | Alanlar | Dikkat |
|---|---|---|
| OpenAI Responses | input_tokens, input_tokens_details.cached_tokens ve .cache_write_tokens, output_tokens, output_tokens_details.reasoning_tokens | input_tokens, önbellekten okunan ve önbelleğe yazılan tokenleri de içerir |
| Anthropic Messages | input_tokens, cache_read_input_tokens, cache_creation_input_tokens, output_tokens, output_tokens_details.thinking_tokens | input_tokens yalnızca son önbellek kesme noktasından (breakpoint) sonrasını sayar; toplam girdi üçünün toplamıdır |
| Gemini generateContent | promptTokenCount, cachedContentTokenCount, toolUsePromptTokenCount, candidatesTokenCount, thoughtsTokenCount | Prompt sayısı önbellekteki tokenleri içerir; düşünme tokenleri çıktı olarak faturalanır. Yeni Interactions API'de alanlar total_input_tokens, total_cached_tokens gibi adlar taşır |
Lansmandan önce aylık maliyet tahmini
Code:
cagri_maliyeti = ( (I - P) * p_in
+ P * p_in * (h * r + (1 - h) * w)
+ O * p_out ) / 1000000
aylik_maliyet = N * g * cagri_maliyeti * (1 - b * d) + eval_ve_test_maliyeti
I, O çağrı başına ortalama girdi / çıktı tokeni (çıktıya reasoning dahil)
P önbelleğe alınabilen ön ek (token) h önbellek isabet oranı (0-1)
r, w önbellek okuma / yazma çarpanı N aylık model çağrısı
g yeniden deneme çarpanı (1.03 = %3) b, d batch payı, batch indirimi (0.5)
p_in, p_out 1 milyon girdi / çıktı tokeninin fiyatı (fiyat sayfasından)
Önbellek yoksa h = 0 ve w = 1 alın; önbelleğe yazmanın ek ücreti olmayan sağlayıcılarda da w = 1'dir. Kullanıcı eylemlerini değil model çağrılarını sayın: beş adımda çalışan bir ajan (agent) beş çağrı yapar ve her çağrının bağlamı bir öncekinden uzundur. I, O ve görev başına çağrı sayısını sezgiyle değil, bir test koşusuyla belirleyin: her özellik için birkaç düzineden birkaç yüze kadar gerçekçi görevi üretimde kullanacağınız işlem hattından (pipeline) geçirin, her usage nesnesini kaydedin ve p50, ortalama ve p95 değerlerini hesaplayın. Ortalama beklenen faturayı, p95 tavanı verir.
Varsayımsal fiyatlarla örnek hesap
Bir e-ticaret sitesinin destek asistanını ele alalım. Fiyatlar hesap kolay olsun diye seçilmiş yuvarlak rakamlardır; bunları varsayımsal kabul edin, gerçek fiyatları fiyat sayfasından alın: 1 milyon girdi tokeni 1,00 $, 1 milyon çıktı tokeni 5,00 $; önbellekten okuma girdi fiyatının 0,10 katı, önbelleğe yazma 1,25 katı.| Test koşusunda ölçülen | Değer |
|---|---|
| Aylık model çağrısı (N) | 300.000; %3'ü yeniden deneniyor (g = 1,03) |
| Sabit ön ek: politikaları içeren sistem prompt'u + üç araç tanımı (P) | 1.800 + 700 = 2.500 token |
| RAG bağlamı | 4 parça × 400 = 1.600 token |
| Çağrı başına girdi tokeni, p50 / ortalama / p95 | 4.760 / 5.600 / 8.350 |
| Çağrı başına çıktı tokeni, p50 / ortalama / p95 | 180 / 260 / 700 |
| Gecelik regresyon değerlendirmesi | 2.000 çağrı × 30 gece = 60.000 çağrı |
| Senaryo | Çağrı başına | Aylık |
|---|---|---|
| "Tipik" (p50) çağrıdan tahmin | 0,00566 $ | 1.749 $ |
| Ortalamadan beklenen maliyet | 0,00690 $ | 2.132 $ |
| Gecelik değerlendirme eklenince (senkron) | 0,00690 $ | 2.132 + 414 = 2.546 $ |
| Ön ek önbellekte, %90 isabet (değerlendirme hâlâ senkron) | 0,00494 $ | 1.526 + 414 = 1.940 $ |
| Değerlendirme de batch'e taşınınca (%50 indirim) | 0,00494 $; değerlendirme çağrısı 0,00345 $ | 1.526 + 207 = 1.733 $ |
| Tavan: her çağrı p95, değerlendirme senkron | 0,01185 $ | 3.662 + 414 = 4.076 $ |
Üç sonuç öne çıkıyor. Medyandan (p50) yapılan tahmin %18 eksik kalıyor, çünkü azınlıktaki uzun konuşmalar ortalamayı yukarı çekiyor. Çıktı tokeni beş kat daha pahalı olduğu hâlde çağrı başına beklenen maliyetin %81'i girdiden geliyor. Önbellek ve batch birlikte, prompt'a dokunmadan faturayı yaklaşık %32 düşürüyor. En küçük önbelleklenebilir uzunluğu da kontrol edin: bugün 4.096 token isteyen bazı Gemini ve Claude modelleri bu 2.500 tokenlik ön eki hiç önbelleğe almaz. Fiyat listeleri ABD doları cinsinden; bütçeyi TL üzerinden planlıyorsanız bir kur senaryosu da ekleyin.
Elektronik tablo düzeni
Code:
A özellik B aylık çağrı C ortalama girdi tokeni D önbelleklenebilir ön ek
E isabet oranı F ortalama çıktı tokeni G yeniden deneme çarpanı H batch payı
I p_in (1M başına $) J p_out (1M başına $) K okuma çarpanı L yazma çarpanı
M batch indirimi N çağrı başına maliyet O aylık maliyet
N2: =((C2-D2)*I2 + D2*I2*(E2*K2+(1-E2)*L2) + F2*J2)/1000000
O2: =B2*G2*N2*(1-H2*M2)
Her özellik ve model için bir satır açın, satırı p50 ve p95 değerleriyle çoğaltın, değerlendirme ve test trafiğine de ayrı bir satır verin: örnekte bu kalem faturanın %16'sı. Formüllerde yalnızca aritmetik işleçler olduğu için Türkçe yerel ayarlı Excel ve Google E-Tablolar'da da aynen çalışır; hücrelere ondalık değerleri virgülle girin (1,03 gibi).
Gerçek kullanımı özellik ve müşteri bazında kaydetmek
Yayına çıktıktan sonra tahmin yerine ölçün. Aşağıdaki sarmalayıcı (wrapper), üç sağlayıcının usage alanlarını tek bir yapıya çevirir ve her çağrıyı etiketleriyle kaydeder:
Python:
import json
from datetime import datetime, timezone
# 1M token başına USD: yer tutucu değerler, güncel fiyatları fiyat sayfasından kopyalayın
PRICES = {"my-model": {"in": 1.00, "read": 0.10, "write": 1.25, "out": 5.00}}
def normalize(provider, u):
"""usage nesnesi -> önbelleksiz girdi, önbellek okuma, önbellek yazma, çıktı."""
if provider == "openai": # Responses API: input_tokens okuma ve yazmayı içerir
d = u.input_tokens_details
read = getattr(d, "cached_tokens", 0) or 0
write = getattr(d, "cache_write_tokens", 0) or 0
return {"inp": u.input_tokens - read - write, "read": read,
"write": write, "out": u.output_tokens} # çıktı reasoning'i içerir
if provider == "anthropic": # Messages API: input_tokens okuma ve yazmayı içermez
return {"inp": u.input_tokens, "read": u.cache_read_input_tokens or 0,
"write": u.cache_creation_input_tokens or 0, "out": u.output_tokens}
if provider == "gemini": # generateContent: prompt sayısı önbellekteki tokenleri içerir
read = u.cached_content_token_count or 0
# araç kullanım prompt tokenleri (ör. URL context sonuçları) girdi olarak faturalanır
return {"inp": (u.prompt_token_count or 0) - read + (u.tool_use_prompt_token_count or 0),
"read": read, "write": 0,
"out": (u.candidates_token_count or 0) + (u.thoughts_token_count or 0)}
raise ValueError(f"bilinmeyen sağlayıcı: {provider}")
def log_llm_call(provider, model, usage, *, feature, tenant, task_id, prompt_version, ok=None):
t = normalize(provider, usage)
p = PRICES[model]
cost = (t["inp"] * p["in"] + t["read"] * p["read"]
+ t["write"] * p["write"] + t["out"] * p["out"]) / 1_000_000
record = {"ts": datetime.now(timezone.utc).isoformat(), "provider": provider,
"model": model, "feature": feature, "tenant": tenant, "task_id": task_id,
"prompt_version": prompt_version, **t, "cost_usd": round(cost, 6), "ok": ok}
print(json.dumps(record)) # üretimde: log hattınıza ya da bir tabloya gönderin
return record
# log_llm_call("openai", "my-model", resp.usage, feature="destek_sohbeti",
# tenant="acme", task_id=konusma_id, prompt_version="v12")
Uzun önbellek ömürleri kullanıyorsanız onları ayrı fiyatlayın (OpenAI bunu ttl_12h_tokens, Anthropic ephemeral_1h_input_tokens alanında raporlar); Gemini'de açıkça oluşturulan önbelleklerin saatlik depolama ücreti de vardır. Ayda bir, kaydınızı OpenAI'ın Usage ve Costs API'leri, Anthropic'in Usage and Cost Admin API'si ve Gemini projenizin faturalandırma raporlarıyla karşılaştırın; aradaki fark genellikle sarmalayıcıyı atlayan bir trafiğe işaret eder.
Faturayı büyüten kalemler
| Kalem | Neden büyür | İlk çözüm |
|---|---|---|
| Konuşma geçmişi | Her tur, önceki turların hepsini yeniden gönderir | Son turlar + özet; önbellek |
| RAG bağlamı | Çağrı başına parça sayısı × parça başına token | Yeniden sıralama (reranking); daha az ve daha küçük parça |
| Yeniden denemeler ve zaman aşımları | Her deneme girdinin tamamını yeniden öder; çıktı sınırında kesilen bir yanıt da yeniden denenmeden önce faturalanmıştır | Artan beklemeyle yeniden deneme (backoff), gerçekçi zaman aşımı, doğrulama hatalarında körü körüne yeniden denememek |
| Ajan ve araç döngüleri | Her adım bağlamı ve araç sonuçlarını yeniden gönderir | Adım sınırı; kullanılmış araç sonuçlarını atmak |
| Uzun yanıtlar | En pahalı token türü | Biçim talimatı, yapılandırılmış çıktı |
| Sistem prompt'u ve araç şemaları | Her çağrıda ödenir | Kısaltmak, önbelleğe almak, her adımda yalnızca gereken araçları sunmak |
| Akıl yürütme düzeyi | Görünmeyen tokenler çıktı fiyatından faturalanır | Basit işlerde düşük düzey |
| Görseller ve dokümanlar | Token sayısı çözünürlük ve sayfa sayısıyla artar | Küçültmek, kırpmak, önce metni çıkarmak |
| Değerlendirme, test ve CI trafiği | Ürün metriklerinde görünmez | Ayrı proje ya da anahtar; batch veya flex |
| Premium katmanlar ve bölgesel işleme | Hızlı modlar ve veri yerleşimi ek ücretleri birim fiyatı artırır | Varsayılan olarak standart katman |
Konuşma geçmişinin etkisini rakamla görelim. 2.500 tokenlik bir ön ek ve tur başına yaklaşık 300 tokenlik artışla birinci tur yaklaşık 2.800, kırkıncı tur yaklaşık 14.500 girdi tokeni gönderir; 10 turluk bir konuşma toplamda yaklaşık 41.500, 40 turluk bir konuşma yaklaşık 346.000 girdi tokeni tutar. Tur sayısı 4 kat, token sayısı 8,3 kat artıyor: p95 buradan gelir. Erişim (retrieval) tarafında, daha az parça gönderip yanıt kaybetmemenin yolu olan yeniden sıralamayı RAG'de parçalama (chunking) ve erişim kalitesi rehberimizde anlattık.
Maliyeti düşürme yolları ve bedelleri
Prompt önbelleği (prompt caching): sabit kısım başa
Önbellek yalnızca birebir aynı ön eki yeniden kullanır; bu yüzden prompt'u en sabitten en değişkene doğru sıralayın: araçlar, sistem talimatları, referans dokümanlar ve örnekler, konuşma geçmişi, en sonda da yeni mesaj. En üste konan bir zaman damgası ya da kullanıcı adı önbelleği o noktadan itibaren bozar; araçları, modeli, çıktı şemasını veya akıl yürütme ayarlarını değiştirmek de aynı sonucu doğurur. Ekim 2026 itibarıyla sağlayıcı kuralları:- OpenAI: varsayılan olarak açık. GPT-5.6 ve sonraki modellerde önbelleğe yazma, varsayılan 30 dakikalık ömür için girdi fiyatının 1,25 katı (Responses API'de seçilebilen 12 saatlik ömür için 2,5 katı), okuma 0,1 katı (bazı modellerde 0,05 katı); en küçük uzunluk 1.024 token. Önceki modellerde yazma ücreti yoktur; saklama süresi prompt_cache_retention ile seçilir: kayıtlar in_memory seçeneğinde genellikle 5–10 dakikalık hareketsizliğe kadar (en fazla bir saat), destekleyen modellerdeki 24h uzatılmış saklamada ise 24 saate kadar tutulur. Okuma indirimi modele göre değişir.
- Anthropic: cache_control ile istek düzeyinde bir kez (otomatik önbellek) ya da en fazla dört blokta açılır. Yazma 5 dakikalık ömür için 1,25 kat, bir saat için 2 kat; okuma çoğu modelde 0,1 kat, en yenilerde daha düşük; her isabet 5 dakikalık ömrü ücretsiz yeniler. En küçük uzunluk modele göre 512 ile 4.096 token arasında değişir; daha kısa prompt'lar hata döndürülmeden, sessizce önbelleksiz işlenir. Bu indirim batch indirimiyle birleşir.
- Gemini: örtük önbellek (implicit caching) 2.5 ve sonraki modellerde varsayılan olarak açık (en küçük uzunluk 2.048 ya da 4.096 token); desteklenen 2.5 ve 3 modellerinde açıkça oluşturulan önbellekler (explicit caching) saatlik depolama ücreti doğurur.
n kez kullanılan bir ön ek n yerine w + (n − 1) × r birim tutar; dolayısıyla önbellek n > (w − r) / (1 − r) olduğunda kâra geçer: w = 1,25 ve r = 0,1 iken ikinci kullanım yeterlidir, 2 ya da 2,5 katlık uzun ömürlü yazmada üç kullanım gerekir. İsabet oranını (önbellekten okunan ÷ toplam girdi tokeni) özellik bazında izleyin; bir dağıtımın (deploy) hemen ardından gelen düşüş, genellikle değişken bir içeriğin önbelleğe alınan kısmın üstüne taşındığını gösterir. Anthropic'te önbellek kaydı ancak ilk yanıt başladığında kullanılabilir olur; paralel çalıştırılan işlerde (fan-out) önce tek bir istek gönderin, kalanları onun yanıtı başladıktan sonra gönderin.
Tahmin formülü, önbelleğe yazmanın sabit ön ekte bittiğini varsayar. Anthropic'in otomatik önbelleği ve OpenAI'ın GPT-5.6 ve sonraki modellerdeki örtük (implicit) modu, kesme noktasını prompt'un sonuna (son önbelleklenebilir bloğa ya da en son uygun mesaja) koyar; böylece her istek, prompt'un yeni eklenen son kısmı için de yazma ücreti öder. Sohbetlerde bu kazandırır, çünkü bir sonraki tur o kısmı önbellekten okur. Son kısmı hiç tekrarlanmayan tek seferlik çağrılarda ise yalnızca açık kesme noktaları kullanın (OpenAI'da explicit modu, Anthropic'te blok düzeyinde cache_control); böylece o kısım sıradan girdi fiyatından faturalanır.
Bekleyebilen işler için toplu işleme (batch) ve flex
Bu yazıyı hazırladığımız sırada üç sağlayıcı da toplu işlemeyi yarı fiyatına sunuyor. OpenAI Batch API 24 saatlik bir pencereyle çalışır ve tek batch'te 50.000 isteğe kadar kabul eder; Anthropic Message Batches çoğunlukla bir saat içinde biter ve 24 saatte tamamlanmazsa süresi dolar; Gemini Batch API 24 saati hedefler ve 48 saati aşan işleri sonlandırır. OpenAI'ın service_tier "flex" seçeneği (beta) ve Gemini'nin Flex inference katmanı (önizleme, 1–15 dakikalık gecikme hedefi) senkron çağrıları batch fiyatına sunar, ama zaman zaman kapasite hatası verir; OpenAI 429 Resource Unavailable hatası için ücret almaz, Gemini ise standart katmana kendiliğinden geçmez. Değerlendirmeler, gecelik özetler, geriye dönük veri zenginleştirme ve raporlar buraya uygundur; kullanıcının yanıt beklediği hiçbir iş uygun değildir.Model yönlendirme (model routing) ve kademeli kullanım
Görev türünü baştan biliyorsanız yönlendirin: sınıflandırma, bilgi çıkarma ve SSS yanıtları küçük modele, çok adımlı akıl yürütme büyük modele. Bilmiyorsanız kademeli kullanın (cascade): önce küçük model yanıtlar, doğrulanabilir bir kontrol başarısız olursa istek büyük modele aktarılır (şema doğrulaması, zorunlu kaynak gösterimi, ayrı bir sınıflandırıcı skoru; modelin kendi beyan ettiği güven zayıf bir sinyaldir). İstek başına maliyet c_küçük + e × c_büyük olduğundan, aktarma oranı e < 1 − c_küçük / c_büyük kaldıkça kademeli kullanım tasarruf sağlar. Küçük modelin fiyatı büyüğünün sekizde biriyse başabaş noktası %87,5 aktarmadır; %20 aktarmada, her zaman büyük modeli kullanmanın maliyetinin %32,5'ini ödersiniz. Kendinden emin yanlış yanıtlar hiç aktarılmaz; değerlendirme setinizde bunlara mutlaka yer verin.Çıktı sınırı, yapılandırılmış çıktı ve akıl yürütme düzeyi
İhtiyacınız olan biçimi isteyin: bilgi çıkarmada düz metin yerine JSON şeması (structured outputs), sohbette "en fazla dört cümle". Çıktı sınırını (OpenAI'da max_output_tokens, Anthropic'te max_tokens, Gemini'de maxOutputTokens) uzunluk ayarı olarak değil güvenlik ağı olarak kullanın, çünkü yarıda kesilen yanıtlar yeniden denenir. OpenAI reasoning modellerinde bu sınır akıl yürütme tokenlerini de kapsar: sınıra ulaşılırsa yanıt eksik (incomplete) döner ama girdi ve akıl yürütme yine faturalanır; OpenAI bu yüzden bu modellerle denemelere başlarken akıl yürütme ve çıktı için en az 25.000 token ayırmayı öneriyor. Kalitenin izin verdiği yerde akıl yürütme düzeyini düşürün: OpenAI'da reasoning.effort, Anthropic'te output_config.effort (çoğu modelde varsayılan high), Gemini'de thinking_level.Bağlamı kırpmak ve geçmişi özetlemek
Son birkaç turu olduğu gibi tutup eskileri birkaç turda bir yenilenen bir özetle değiştirin; her yenileme ayrı bir model çağrısıdır ve önbelleği o noktadan yeniden başlatır. Kullanılmış araç sonuçlarını bağlamdan çıkarın ve yalnızca yanıtın ihtiyaç duyduğu parçaları gönderin. Bunun bir kısmını sağlayıcı sunucu tarafında yapabilir: Anthropic'in bağlam düzenleme (context editing) özelliği eski araç sonuçlarını temizler, OpenAI ve Anthropic'in sıkıştırma (compaction) özellikleri ise eski turları sunucuda yazılan bir özetle değiştirir. Değişikliği isabet oranıyla değil toplam girdi maliyetiyle değerlendirin: OpenAI, sıkıştırmanın isabet oranını düşürüp yine de tasarruf sağlayabileceğini belirtiyor.Uygulama düzeyinde yanıt önbelleği
Yanıt önbelleği saklanmış bir cevabı döndürür; prompt önbelleğinin aksine davranışı değiştirir. Birebir eşleşen önbellekte anahtar olarak normalleştirilmiş girdi, model, prompt sürümü, parametreler ve müşteri ya da yetki kapsamının birlikte alınmış özetini (hash) kullanın; bir TTL tanımlayın ve dokümanlar, prompt ya da model değişince kayıtları geçersiz kılın. Anlamsal önbellek (semantic cache) benzer soruları eşleştirir, ama "Bunu iade edebilir miyim?" ile "Bunu açtıktan sonra iade edebilir miyim?" gömme (embedding) uzayında birbirine yakındır ve farklı yanıt gerektirir: yüksek eşik kullanın, yalnızca düşük riskli niyetlerde açın, isabetlerden örnekleri gözden geçirin ve kayıtları müşteriler arasında asla paylaşmayın.Uzun prompt yerine ince ayar (fine-tuning)?
İnce ayarlı küçük bir model uzun bir few-shot prompt'un yerini alabilir; bedeli eğitim maliyeti, farklı token fiyatları, temel model kullanımdan kaldırıldığında yeniden eğitim ve platform riskidir: OpenAI'ın fiyat sayfası, ince ayar platformunun kademeli olarak kapatıldığını ve yeni kullanıcı kabul etmediğini söylüyor. Uzun prompt'u önbelleğe almak, tasarrufun büyük kısmını bakım yükü olmadan sağlayabilir.Kendi sunucunuzda çalıştırma: başabaş noktasını kendi rakamlarınızla hesaplayın
Code:
selfhost_aylik = gpu_sayisi * gpu_saatlik_ucret * calisma_saati
+ operasyon_saati * personel_saatlik_maliyeti
+ izleme + depolama + ag + yedek_kapasite
sunulan_token = saniyede_surekli_token * 3600 * calisma_saati * kullanim_orani
selfhost_1M = selfhost_aylik / (sunulan_token / 1000000)
api_1M = önbellek ve batch sonrası karma API fiyatı (1M token başına)
Kendi sunucunuz ancak selfhost_1M, api_1M'in altında kalırsa ve kalite değerlendirme setinizden geçerse kazandırır. Sürekli işlem hacmini (throughput) üreticinin açıkladığı tepe değerden değil, kendi çıkarım (inference) sunucunuzla (örneğin vLLM ya da SGLang), nicemleme (quantization) ayarınızla ve prompt karışımınızla, hedef gecikmenizde ölçün. Asıl tuzak kullanım oranıdır: GPU gece boyunca da ücretlenir, trafik ise mesai saatlerinde zirve yapar. En az iki kopya (replica), güncellemeler, güvenlik yamaları ve nöbet için bütçe ayırın. Veri yerleşimi (data residency) ya da KVKK gereksinimleri, rakamlardan bağımsız olarak kararı belirleyebilir.
İzleme ve koruma önlemleri
- Maliyet ataması (cost attribution): her çağrıyı özellik, müşteri, kullanıcı, görev, prompt sürümü ve modelle etiketleyin. Her özellik ya da ortam için ayrı bir OpenAI projesi veya Anthropic çalışma alanı (workspace) ve ayrı API anahtarları açın ki sağlayıcının raporları da aynı şekilde bölünsün; değerlendirme ve CI trafiğini ayrı tutun.
- Bütçeler: OpenAI'da kuruluş ve proje düzeyinde harcama uyarıları ile kesin aylık limitler var (limite ulaşılınca istekler organization_spend_limit_exceeded ya da project_spend_limit_exceeded koduyla 429 döndürür; uygulama anlık değildir); Anthropic çalışma alanlarında uyarı eşikli aylık harcama limitleri bulunuyor; Gemini'de faturalandırma hesabı düzeyinde ve (deneysel olarak) proje düzeyinde aylık harcama tavanları var ve faturalandırma verisi işlenene kadar bu tavanlar aşılabiliyor. Bunlara ek olarak özellik başına günlük bütçe tanımlayın, %50, %80 ve %100'de uyarı verin.
- Anomali tespiti: saatlik token kullanımını geçen haftanın aynı saatiyle karşılaştırın; görev başına çağrı sayısı (döngüler), p95 çıktıdaki sıçramalar ve dağıtım sonrası düşen isabet oranı için alarm kurun.
- Kotalar ve acil kapatma anahtarı (kill switch): kullanıcı ve müşteri başına günlük token kotası kötüye kullanımı ve kontrolden çıkan betikleri sınırlar; bir özellik bayrağı (feature flag) ise özelliği dağıtım yapmadan kapatır ya da kısar (daha küçük model, araçsız çalışma, kısa bağlam).
- KPI: başarılı görev başına maliyet. Çağrı başına maliyet düşerken bu değer artabilir; örneğin daha ucuz ama daha çok yeniden deneme gerektiren bir modele geçtiğinizde.
Çağrı kaydı PostgreSQL'e yüklendiğinde haftalık KPI tek bir sorgudur:
SQL:
-- llm_calls: her model çağrısı için bir satır (ts timestamptz, feature text, task_id text,
-- cost_usd numeric, ok boolean; ok, görevi bitiren çağrıda doldurulur)
WITH tasks AS (
SELECT feature, task_id,
min(ts) AS started_at,
count(*) AS calls,
sum(cost_usd) AS cost_usd,
bool_or(ok) AS ok
FROM llm_calls
GROUP BY feature, task_id
)
SELECT feature,
date_trunc('week', started_at) AS week,
count(*) AS tasks,
round(avg(calls), 1) AS avg_calls_per_task,
round(sum(cost_usd), 2) AS spend_usd,
round(sum(cost_usd) / nullif(count(*) FILTER (WHERE ok), 0), 4)
AS cost_per_successful_task
FROM tasks
GROUP BY 1, 2
ORDER BY 2 DESC, 5 DESC;
Drift, izleme ve geri alma (rollback) için LLMOps: maliyet, drift, izleme ve geri alma konusuna, API'nin temelleri için OpenAI API ile geliştirme rehberine bakabilirsiniz.
Sık yapılan hatalar
- Tipik bir istekten tahmin yapmak: tipik istek medyandır; fatura için ortalamayı, tavan için p95'i kullanın.
- Yeniden denemeleri yok saymak: zaman aşımları ve JSON doğrulaması başarısız olunca yapılan yeniden istekler girdinin tamamını tekrar öder.
- Tüm geçmişi her turda göndermek: konuşmanın girdi maliyeti, uzunluğunun karesiyle kabaca orantılı büyür.
- Gizli girdiyi unutmak: araç şemaları, araç kullanım prompt'u, görseller ve önceki turlardan taşınan düşünme blokları.
- Değişken veriyi prompt'un başına koymak: ilk satırdaki tek bir zaman damgası her isteği önbellek ıskasına (cache miss) çevirir.
- Reasoning modellerinde düşük çıktı sınırı: akıl yürütmenin parasını ödersiniz, eksik bir yanıt alırsınız.
- Yanlış tokenizer ile saymak: başka bir sağlayıcının ya da eski bir model kuşağının tokenizer'ı veya İngilizce örnek metin.
- Kaliteyi ölçmeden maliyet kısmak: değerlendirme seti olmadan yapılan tasarruf, düpedüz daha kötü bir ürün olabilir.
Sık sorulan sorular
Türkçe bir kelime kaç token eder?Örneklerimizde o200k_base ile yaklaşık 2,1 token (İngilizcede yaklaşık 1,1), eski cl100k_base ile yaklaşık 3 token. Aynı içerik Türkçede o200k_base ile yaklaşık %30, cl100k_base ile yaklaşık %80 daha fazla token tuttu. Kendi metninizi, kullanacağınız modelle ölçün.
Prompt önbelleği çıktıyı değiştirir mi?
Hayır. OpenAI dokümantasyonu bunu açıkça söylüyor: önbellek işlenmiş ön eki yeniden kullanır, çıktının nasıl üretildiğini değiştirmez. Uygulama düzeyindeki yanıt önbelleği ise farklıdır, çünkü saklanmış bir cevabı döndürür.
Batch ne kadar yavaş?
OpenAI ve Gemini 24 saatlik bir pencereyle çalışır ve çoğu zaman daha erken biter; Anthropic, batch'lerin çoğunun bir saat içinde bittiğini söylüyor. Planınızı pencerenin tamamına göre yapın; dakikalar kabul edilebilir ama saatler kabul edilemezse flex katmanına bakın.
Kendi sunucumuzda çalıştırmak daha mı ucuz?
Yalnızca iki koşul birlikte sağlanırsa: kullanım oranı yüksek ve sürekli olmalı, kalite çıtanızı karşılayan açık ağırlıklı (open-weight) bir model de bulunmalı. Başabaş formülünü ölçülmüş işlem hacmi, gerçek GPU ücretleri ve personel zamanıyla doldurun.
Aylık bütçeyi nasıl belirlerim?
Beklenen maliyeti kayıtlarınızdan alın (çağrı başına ortalama maliyet × hacim, artı değerlendirme trafiği), bir güvenlik payı ekleyin ve uyarıları bunun altına kurun. Kesin limitin trafiği nerede durduracağına p95 senaryosuyla karar verin ve her özelliğe ayrı bütçe verin ki kontrolden çıkan tek bir özellik diğerlerinin payını tüketmesin.
Sonuç ve sonraki adımlar
Gerçekte ne gönderildiğini saydığınızda LLM API faturası öngörülebilir hâle gelir: sabit ön ek, geçmiş, erişim bağlamı, araç şemaları, akıl yürütme ve yeniden denemeler. Tahmini ölçülmüş bir dağılımdan yapın, her çağrıyı maliyet ataması etiketleriyle kaydedin ve başarılı görev başına maliyeti izleyerek her seferinde tek bir ayarı değiştirin.- Her özellik için birkaç düzine gerçekçi görevi işlem hattınızdan geçirin; p50, ortalama ve p95 değerlerini kaydedin.
- Elektronik tabloyu resmi fiyat sayfalarındaki güncel fiyatlarla doldurun.
- Kayıt sarmalayıcısını her model çağrısının önüne koyun.
- Sabit ön eki her prompt'un en başına taşıyın ve isabet oranını usage alanlarından doğrulayın.
- Değerlendirmeleri ve gecelik işleri batch'e taşıyın; sağlayıcı tarafında ve özellik bazında bütçe uyarıları kurun.
AIOR'un yapay zekâ ve veri mühendisliği ekibi, kurumsal bilgi erişimi ve veri analizi için yapay zekâ çözümlerini doğrulama ve izleme adımlarını baştan tanımlayarak geliştiriyor. Maliyet modelinize ikinci bir göz isterseniz rakamlarınızı bu konuya yazabilirsiniz.
An LLM feature rarely overruns its budget because the model is expensive. The bill grows from tokens nobody counted: history resent on every turn, ten RAG chunks where three would do, tool schemas on every call, retries, nightly evaluations, and reasoning tokens that never appear in the answer. This guide shows how to estimate the monthly LLM API cost before launch, measure it afterwards, and reduce it without losing quality.
There is no price table here on purpose: prices change often and vary by model, service tier, cache lifetime, prompt length and region. Plug current numbers from the official OpenAI, Anthropic and Google Gemini pricing pages into the formulas below. Provider details were checked against official documentation in October 2026; they are provider- and model-specific and will change.
How LLM API billing works
- Input and output are priced separately. Output costs roughly 4 to 8 times as much per token on the price lists we checked, yet input is often the bigger line: in the example below, each call sends about 20 times more tokens than it receives.
- Reasoning tokens are billed as output on OpenAI's reasoning models, Claude with thinking and Gemini's thinking models, even when you see only a summary. They appear in the usage object, not in the text.
- Cached input has its own rates: cheap reads and, at some providers, a premium for writes.
- Everything you send is input, on every call: system prompt, tool schemas, examples, RAG context and history. Anthropic also adds a hidden tool-use prompt of a few hundred tokens whenever tools are present.
- Images become tokens: Claude counts 28×28-pixel patches, so a 1000×1000 image is 1,296 tokens. Gemini's token guide counts a small image as 258 tokens and tiles larger ones, while on Gemini 3 models the media_resolution parameter sets the per-image budget (about 1,120 tokens by default, 280 at low).
- Modifiers stack: batch and flex tiers are cheaper, fast tiers dearer; some models charge more above a prompt-length threshold (272K tokens on some OpenAI models, 200K on some Gemini models, 100,000 on Claude Haiku 5.5); OpenAI and Anthropic add 10% for regional or US-only processing on newer models; web search and other server-side tools are billed per call or per session on top of their tokens.
Rate limits have their own sub-forum; this guide covers cost only.
Tokenizers differ: measure Turkish text
Tokenizers differ by provider and even by model generation: Anthropic states that Claude 4.7 and later models produce about 30% more tokens for the same text than earlier ones. Language matters too. We counted two pairs of parallel Turkish and English texts with identical content (a customer message and a support assistant's system prompt) using OpenAI's tiktoken library:| Encoding | Tokens per Turkish word | Tokens per English word | Turkish ÷ English tokens, same content |
|---|---|---|---|
| o200k_base (GPT-4o, GPT-4.1, GPT-5 in tiktoken's model map) | 2.06–2.18 | 1.13–1.14 | 1.29–1.31 |
| cl100k_base (GPT-4 and GPT-3.5 era) | 2.79–3.11 | 1.14–1.15 | 1.76–1.83 |
Per word, agglutinative Turkish needs about twice the tokens; per unit of content the gap is about 30% with the newer encoding, and that is the ratio the bill sees. Two samples are not a benchmark: count your own prompts with the exact model you will use, through OpenAI's input token count endpoint, Anthropic's free count_tokens endpoint or Gemini's countTokens.
Read the usage object correctly
The fields mean different things at different providers, and mixing them up double-counts cached tokens:| Provider and API | Fields | Watch out |
|---|---|---|
| OpenAI Responses | input_tokens, input_tokens_details.cached_tokens and .cache_write_tokens, output_tokens, output_tokens_details.reasoning_tokens | input_tokens includes cache reads and writes |
| Anthropic Messages | input_tokens, cache_read_input_tokens, cache_creation_input_tokens, output_tokens, output_tokens_details.thinking_tokens | input_tokens counts only what follows the last cache breakpoint; total input is the sum of the three |
| Gemini generateContent | promptTokenCount, cachedContentTokenCount, toolUsePromptTokenCount, candidatesTokenCount, thoughtsTokenCount | The prompt count includes cached tokens; thoughts are billed as output. The newer Interactions API uses total_input_tokens, total_cached_tokens and similar fields |
Estimating the monthly bill before launch
Code:
cost_per_call = ( (I - P) * p_in
+ P * p_in * (h * r + (1 - h) * w)
+ O * p_out ) / 1000000
monthly_cost = N * g * cost_per_call * (1 - b * d) + eval_and_test_cost
I, O mean input / output tokens per call (output incl. reasoning)
P cacheable prefix tokens h cache hit rate (0-1)
r, w cache read / write multipliers N model calls per month
g retry factor (1.03 = 3%) b, d batched share, batch discount (0.5)
p_in, p_out price per 1M input / output tokens, from the pricing page
Without caching, h = 0 and w = 1; w is also 1 where cache writes cost nothing extra. Count model calls, not user actions: a five-step agent makes five calls, each with a longer context. Take I, O and calls per task from a test run, not from intuition: push a few dozen to a few hundred realistic tasks per feature through the pipeline you will run in production, log every usage object, and compute p50, mean and p95. The mean gives the expected bill, p95 the ceiling.
Worked example with hypothetical prices
Take a support assistant for an online shop. The prices are round numbers picked for easy arithmetic; treat them as hypothetical and take real ones from the pricing page: $1.00 per million input tokens, $5.00 per million output tokens, cache reads at 0.10× and writes at 1.25× the input price.| Measured in the test run | Value |
|---|---|
| Model calls per month (N) | 300,000; 3% retried (g = 1.03) |
| Static prefix: system prompt with policies + three tool definitions (P) | 1,800 + 700 = 2,500 tokens |
| RAG context | 4 chunks × 400 = 1,600 tokens |
| Input tokens per call, p50 / mean / p95 | 4,760 / 5,600 / 8,350 |
| Output tokens per call, p50 / mean / p95 | 180 / 260 / 700 |
| Nightly regression evaluation | 2,000 calls × 30 nights = 60,000 calls |
| Scenario | Per call | Per month |
|---|---|---|
| Estimate from a "typical" (p50) call | $0.00566 | $1,749 |
| Expected cost, from the mean | $0.00690 | $2,132 |
| Plus the nightly evaluation, synchronous | $0.00690 | $2,132 + $414 = $2,546 |
| Prefix cached, 90% hit rate (evaluation still synchronous) | $0.00494 | $1,526 + $414 = $1,940 |
| Evaluation moved to batch as well (−50%) | $0.00494; evaluation call $0.00345 | $1,526 + $207 = $1,733 |
| Ceiling: every call at p95, evaluation synchronous | $0.01185 | $3,662 + $414 = $4,076 |
Three lessons. The p50 estimate is 18% low, because a minority of long conversations pulls the mean up. Input is 81% of the expected cost per call despite the five-times output price. Caching and batch together cut the bill by about 32% without touching the prompt. Check the minimum cacheable length, too: some current Gemini and Claude models need 4,096 tokens and would not cache this 2,500-token prefix at all. Prices are in US dollars, so add an exchange-rate scenario if you budget in another currency.
Spreadsheet layout
Code:
A feature B calls per month C mean input tokens D cacheable prefix
E cache hit rate F mean output tokens G retry factor H batch share
I p_in ($ per 1M) J p_out ($ per 1M) K read multiplier L write multiplier
M batch discount N cost per call O monthly cost
N2: =((C2-D2)*I2 + D2*I2*(E2*K2+(1-E2)*L2) + F2*J2)/1000000
O2: =B2*G2*N2*(1-H2*M2)
Use one row per feature and model, duplicate it with the p50 and p95 values, and give evaluation and test traffic a row of its own: in the example it is 16% of the bill.
Logging real usage per feature and tenant
After launch, measure instead of estimating. This wrapper maps the three providers' usage fields onto one shape and stores each call with its tags:
Python:
import json
from datetime import datetime, timezone
# USD per 1M tokens: placeholders, copy current values from the pricing page
PRICES = {"my-model": {"in": 1.00, "read": 0.10, "write": 1.25, "out": 5.00}}
def normalize(provider, u):
"""Usage object -> uncached input, cache reads, cache writes, output."""
if provider == "openai": # Responses API: input_tokens includes reads and writes
d = u.input_tokens_details
read = getattr(d, "cached_tokens", 0) or 0
write = getattr(d, "cache_write_tokens", 0) or 0
return {"inp": u.input_tokens - read - write, "read": read,
"write": write, "out": u.output_tokens} # output includes reasoning
if provider == "anthropic": # Messages API: input_tokens excludes reads and writes
return {"inp": u.input_tokens, "read": u.cache_read_input_tokens or 0,
"write": u.cache_creation_input_tokens or 0, "out": u.output_tokens}
if provider == "gemini": # generateContent: prompt count includes cached tokens
read = u.cached_content_token_count or 0
# tool-use prompt tokens (e.g. URL context results) are billed as input
return {"inp": (u.prompt_token_count or 0) - read + (u.tool_use_prompt_token_count or 0),
"read": read, "write": 0,
"out": (u.candidates_token_count or 0) + (u.thoughts_token_count or 0)}
raise ValueError(f"unknown provider: {provider}")
def log_llm_call(provider, model, usage, *, feature, tenant, task_id, prompt_version, ok=None):
t = normalize(provider, usage)
p = PRICES[model]
cost = (t["inp"] * p["in"] + t["read"] * p["read"]
+ t["write"] * p["write"] + t["out"] * p["out"]) / 1_000_000
record = {"ts": datetime.now(timezone.utc).isoformat(), "provider": provider,
"model": model, "feature": feature, "tenant": tenant, "task_id": task_id,
"prompt_version": prompt_version, **t, "cost_usd": round(cost, 6), "ok": ok}
print(json.dumps(record)) # in production: send to your log pipeline or a table
return record
# log_llm_call("openai", "my-model", resp.usage, feature="support_chat",
# tenant="acme", task_id=conversation_id, prompt_version="v12")
Price long cache lifetimes separately if you use them (OpenAI reports ttl_12h_tokens, Anthropic ephemeral_1h_input_tokens), and remember that explicit Gemini caches also bill storage per hour. Once a month, reconcile with OpenAI's Usage and Costs APIs, Anthropic's Usage and Cost Admin API and your Gemini project's billing reports; a gap usually means traffic that bypasses the wrapper.
What drives the bill up
| Driver | Why it grows | First fix |
|---|---|---|
| Conversation history | Each turn resends all earlier turns | Recent-turn window plus summary; caching |
| RAG context | Chunks per call × tokens per chunk | Rerank; send fewer, smaller chunks |
| Retries and timeouts | Each retry pays the full input again, and a response cut off at the output limit was already billed before the retry | Backoff, realistic timeouts, no blind retries on validation errors |
| Agent and tool loops | Each step resends context plus tool results | Step limit; drop tool results once used |
| Verbose output | The dearest token type | Format instructions, structured output |
| System prompt and tool schemas | Paid on every call | Trim, cache, offer only the tools a step needs |
| Reasoning effort | Invisible tokens billed as output | Lower effort for simple tasks |
| Images and documents | Tokens scale with resolution and pages | Downscale, crop, extract text first |
| Evaluation, test and CI traffic | Invisible in product metrics | Separate project or key; batch or flex |
| Premium tiers and regional processing | Fast modes and residency uplifts raise the rate | Standard tier by default |
History deserves a number. With a 2,500-token prefix and about 300 tokens added per turn, turn 1 sends about 2,800 input tokens and turn 40 about 14,500; a 10-turn conversation totals about 41,500 input tokens, a 40-turn one about 346,000. Four times the turns, 8.3 times the tokens: that is where p95 comes from. For retrieval, our RAG guide on chunking and retrieval quality covers the reranking that lets you send fewer chunks without losing answers.
Ways to reduce cost, and their trade-offs
Prompt caching: stable prefix first
Caching reuses only an identical prefix, so order prompts from most to least stable: tools, system instructions, reference documents and examples, history, then the new message. A timestamp or user name near the top, or a change of tools, model, output schema or reasoning settings, breaks the cache from that point on. Provider rules as of October 2026:- OpenAI: on by default. On GPT-5.6 and later, writes cost 1.25× input for the default 30 minutes (2.5× for the 12-hour option in the Responses API) and reads 0.1× (0.05× on some models), with a 1,024-token minimum. Earlier models charge nothing for writes and set retention with prompt_cache_retention: in_memory entries typically last 5 to 10 minutes of inactivity (at most an hour), and 24h extended retention, where supported, keeps them up to 24 hours. Read discounts are model-specific.
- Anthropic: cache_control at the top level (automatic) or on up to four blocks. Writes cost 1.25× for 5 minutes and 2× for one hour; reads 0.1× on most models and less on the newest; each hit refreshes the 5-minute lifetime for free. The minimum is 512 to 4,096 tokens by model, and shorter prompts are silently not cached. The discount stacks with batch.
- Gemini: implicit caching is on by default for 2.5 and newer models (minimum 2,048 or 4,096 tokens); explicit caches on supported 2.5 and 3 models add an hourly storage fee.
A prefix used n times costs w + (n − 1) × r instead of n, so caching pays once n > (w − r) / (1 − r): at w = 1.25 and r = 0.1 the second use already wins, while a 2× or 2.5× long-lifetime write needs three uses. Track the hit rate (cached ÷ total input tokens) per feature; a drop right after a deploy usually means variable content moved up. On Anthropic a cache entry becomes usable only once the first response starts, so in fan-out jobs send one request first and the rest once its response has started.
The estimate formula assumes that cache writes stop at the stable prefix. Anthropic's automatic caching and OpenAI's implicit mode on GPT-5.6 and later put the breakpoint at the end of the prompt (the last cacheable block or the latest eligible message), so every request also pays the write rate on its new tail. In a chat this pays off, because the next turn reads the tail back; for one-off calls whose tail never repeats, use explicit breakpoints only (OpenAI's explicit mode, block-level cache_control at Anthropic) so the tail is billed as ordinary input.
Batch and flex for work that can wait
At the time of writing all three providers sell batch processing at half price. OpenAI's Batch API has a 24-hour window and takes up to 50,000 requests per batch; Anthropic's Message Batches mostly finish within an hour and expire after 24 hours; Gemini's Batch API targets 24 hours and expires jobs after 48. OpenAI's service_tier "flex" (beta) and Gemini's Flex inference (preview, 1 to 15 minute latency target) serve synchronous calls at batch prices with occasional capacity errors; OpenAI does not charge for its 429 Resource Unavailable, and Gemini does not fall back to the standard tier. Use them for evaluations, nightly summaries, backfills and reports, never for a user who is waiting.Model routing and cascades
Route by task type when you know it: classification, extraction and FAQ answers to a small model, multi-step reasoning to a large one. Otherwise cascade: the small model answers and the request escalates when a verifiable check fails (schema validation, a required citation, a classifier score; self-reported confidence is weak). Cost per request is c_small + e × c_large, so the cascade saves money while the escalation rate e < 1 − c_small / c_large. With a small model at one eighth of the price, break-even is 87.5% escalation, and at 20% escalation you pay 32.5% of what always using the large model would cost. Confident wrong answers never escalate, so make sure your evaluation set contains them.Output limits, structured output and reasoning effort
Ask for the format you need: a JSON schema (structured outputs) for extraction, "at most four sentences" for chat. Treat the output limit (max_output_tokens at OpenAI, max_tokens at Anthropic, maxOutputTokens at Gemini) as a safety net, since truncated answers get retried. On OpenAI reasoning models it includes reasoning tokens: when it is hit, the response is incomplete while input and reasoning are still billed, so OpenAI suggests reserving at least 25,000 tokens for reasoning and output when you start experimenting. Lower the reasoning effort where quality allows: reasoning.effort at OpenAI, output_config.effort at Anthropic (most models default to high), thinking_level at Gemini.Trimming context and summarizing history
Keep recent turns verbatim and replace older ones with a summary refreshed every few turns; each refresh is a model call and restarts the cache. Drop tool results once used and send only the chunks the answer needs. Providers can do part of this server-side: Anthropic's context editing clears old tool results, and the compaction features of OpenAI and Anthropic replace older turns with a summary written on the server. Judge by total input cost, not hit rate: OpenAI notes that compaction can lower the hit rate and still save money.Application-level response caching
A response cache returns a stored answer, so unlike prompt caching it changes behavior. Key an exact cache on a hash of the normalized input, model, prompt version, parameters and tenant or permission scope, with a TTL and invalidation when documents, prompt or model change. A semantic cache matches similar questions, but "Can I return this?" and "Can I return this after opening it?" embed close together and need different answers: use strict thresholds and low-risk intents only, review sampled hits, and never share entries across tenants.Fine-tuning instead of long prompts?
A fine-tuned smaller model can replace a long few-shot prompt, at the price of training, different per-token rates, retraining when the base model is retired, and platform availability: OpenAI's pricing page says its fine-tuning platform is being wound down and closed to new users. Caching the long prompt often captures most of the saving with no maintenance.Self-hosting: compute the break-even with your own numbers
Code:
selfhost_monthly = gpu_count * gpu_hourly_rate * hours_running
+ ops_hours * staff_hourly_cost
+ monitoring + storage + network + spare_capacity
tokens_served = sustained_tokens_per_second * 3600 * hours_running * utilization
selfhost_per_1M = selfhost_monthly / (tokens_served / 1000000)
api_per_1M = blended API price per 1M tokens, after caching and batch
Self-hosting wins only if selfhost_per_1M is below api_per_1M at a quality your evaluation set accepts. Measure sustained throughput with your own serving stack (vLLM or SGLang, for example), quantization and prompt mix at your latency target, not from a vendor's peak figure. Utilization is the usual trap: GPUs bill all night while traffic peaks in office hours. Budget for at least two replicas, patches and on-call time. Data-residency or KVKK (Türkiye's personal data protection law) requirements can decide the matter regardless of cost.
Monitoring and guardrails
- Attribution: tag every call with feature, tenant, user, task, prompt version and model. Give each feature or environment its own OpenAI project or Anthropic workspace and API keys so the provider's reports split the same way, and keep evaluation and CI traffic separate.
- Budgets: OpenAI has spend alerts and hard limits per organization and project (a reached hard limit returns 429 with organization_spend_limit_exceeded or project_spend_limit_exceeded, and enforcement is not instantaneous); Anthropic workspaces have monthly spend limits with alert thresholds; Gemini has monthly spend caps per billing account and, experimentally, per project, which can be overshot while billing data catches up. Add your own daily budget per feature with alerts at 50, 80 and 100%.
- Anomalies: compare tokens per hour with the same hour last week, and alert on calls per task (loops), on jumps in p95 output and on a falling cache hit rate after a deploy.
- Caps and kill switch: daily token quotas per user and tenant contain abuse and runaway scripts; a feature flag disables or degrades a feature (smaller model, no tools, shorter context) without a deploy.
- KPI: cost per successful task. Cost per call can fall while it rises, for example after a move to a cheaper model that needs more retries.
With the call log loaded into PostgreSQL, the weekly KPI is one query:
SQL:
-- llm_calls: one row per model call (ts timestamptz, feature text, task_id text,
-- cost_usd numeric, ok boolean set on the call that finished the task)
WITH tasks AS (
SELECT feature, task_id,
min(ts) AS started_at,
count(*) AS calls,
sum(cost_usd) AS cost_usd,
bool_or(ok) AS ok
FROM llm_calls
GROUP BY feature, task_id
)
SELECT feature,
date_trunc('week', started_at) AS week,
count(*) AS tasks,
round(avg(calls), 1) AS avg_calls_per_task,
round(sum(cost_usd), 2) AS spend_usd,
round(sum(cost_usd) / nullif(count(*) FILTER (WHERE ok), 0), 4)
AS cost_per_successful_task
FROM tasks
GROUP BY 1, 2
ORDER BY 2 DESC, 5 DESC;
For drift, monitoring and rollback, see LLMOps: cost, drift, monitoring and rollback; for API basics, developing with the OpenAI API.
Common mistakes
- Estimating from a typical request: that is the median; use the mean for the bill and p95 for the ceiling.
- Ignoring retries: timeouts and re-asks after failed JSON validation pay the full input again.
- Resending the whole history: a conversation's input cost then grows roughly with the square of its length.
- Forgetting hidden input: tool schemas, the tool-use prompt, images and thinking blocks carried over from earlier turns.
- Variable data at the top of the prompt: one timestamp in the first line makes every request a cache miss.
- A low output limit on reasoning models: you pay for the reasoning and get an incomplete answer.
- The wrong tokenizer: another provider's, an older model generation's, or English sample text.
- Cutting cost without measuring quality: without an evaluation set, a saving can simply be a worse product.
Frequently asked questions
How many tokens is a Turkish word?In our samples, about 2.1 tokens with o200k_base (English: about 1.1) and about 3 with the older cl100k_base. The same content took about 30% more tokens in Turkish with o200k_base and about 80% more with cl100k_base. Measure your own text with the model you will use.
Does prompt caching change the output?
No. OpenAI's documentation says so directly: caching reuses the processed prefix and does not change how output is generated. An application-level response cache is different, because it returns a stored answer.
How slow is batch?
OpenAI and Gemini work to a 24-hour window and often finish sooner; Anthropic says most batches finish within an hour. Plan for the full window, and use a flex tier when minutes are acceptable but hours are not.
Is self-hosting cheaper?
Only with high, steady utilization and an open-weight model that meets your quality bar. Fill in the break-even formula with measured throughput, real GPU rates and staff time.
How do I set a monthly budget?
Take the expected cost from your logs (mean cost per call times volume, plus evaluation traffic), add a margin and alert below it. Use the p95 scenario to decide where a hard limit stops traffic, and give each feature its own budget so one runaway feature cannot exhaust the rest.
Conclusion and next steps
An LLM API bill becomes predictable once you count what is actually sent: static prefix, history, retrieval context, tool schemas, reasoning and retries. Estimate from a measured distribution, log every call with attribution tags, and change one lever at a time while watching cost per successful task.- Run a few dozen realistic tasks per feature through your pipeline and record p50, mean and p95.
- Fill in the spreadsheet with today's prices from the official pricing pages.
- Put the logging wrapper in front of every model call.
- Move the stable prefix to the top of each prompt and confirm the hit rate in the usage fields.
- Move evaluations and nightly jobs to batch, and set provider-side and per-feature budget alerts.
AIOR's AI and data engineering team builds AI solutions for enterprise knowledge retrieval and data analytics, with validation and monitoring defined from the start. If you want a second opinion on your cost model, post your numbers in this thread.
Last edited: