Cache-Control, bir HTTP yanıtının (ve isteğin) tarayıcı önbelleğinde ya da CDN, proxy gibi paylaşılan önbelleklerde saklanıp saklanamayacağını, ne kadar süre taze sayılacağını ve yeniden kullanılmadan önce sunucuya sorulup sorulmayacağını belirleyen başlıktır. ETag ve Last-Modified ise yanıtın sürümünü tanımlayan doğrulayıcılardır: süresi dolan bir kopya için tarayıcı If-None-Match veya If-Modified-Since içeren koşullu bir istek gönderir, içerik değişmemişse sunucu gövdesiz bir 304 Not Modified ile yanıt verir.
Bu yazı başlıkların başvuru tarafını anlatır: her yönergenin tam anlamı, sık karıştırılan no-cache ile no-store farkı, tazelik hesabı, Vary ile önbellek anahtarı, koşullu isteklerin akışı ve çoğu sitenin işini gören iki desen. Önbelleğin genel kavramını, katmanlarını ve CDN mantığını önbellek nedir, nasıl çalışır yazısında bulabilirsiniz; serinin tamamı için Web API öğrenme rehberi sayfasına bakın.
Önbellek türleri: özel ve paylaşılan
HTTP önbellek belirtimi iki ana tür tanımlar. Özel önbellek (private cache) tek bir istemciye bağlıdır; tipik örneği tarayıcının kendi önbelleğidir. İçindeki yanıt başka kullanıcıyla paylaşılmadığı için oturum açmış kullanıcıya özel bir sayfayı saklamasında sakınca yoktur. Paylaşılan önbellek (shared cache) ise istemci ile kaynak sunucu arasında durur ve tek bir kopyayı birçok kullanıcıya dağıtır. MDN paylaşılan önbellekleri ikiye ayırır: kurumların ağına yerleştirdiği proxy önbellekleri ve servis sahibinin bilerek kurduğu yönetilen önbellekler (ters proxy, CDN, Cache API ile çalışan service worker).
Bu ayrım bütün yönergelerin temelidir, çünkü en ciddi hata kişisel içeriğin paylaşılan önbelleğe düşmesidir. MDN, oturum açıldıktan sonra dönen ve çerezle yönetilen yanıtlarda private yönergesinin unutulmasının, o yanıtın başka kullanıcılara sunulmasına ve kişisel verinin sızmasına yol açabileceğini açıkça belirtir. Çerezin varlığı tek başına yanıtı özel yapmaz; bunu yönergeyle söylemeniz gerekir.
HTTPS yaygınlaştıktan sonra yoldaki eski proxy önbelleklerinin çoğu şifreli trafiği yalnızca tünelleyebiliyor, içeriği göremiyor. Yönetilen önbelleklerde ise davranış ürüne göre değişir: bir CDN, standart başlıkların yanında kendi panelini, API ile önbellek temizlemeyi ve yalnızca kendisinin anladığı ek başlıkları sunabilir. Bu yüzden MDN, kullandığınız yönetilen önbelleğin belgesini okumanızı önerir.
Cache-Control sözdizimi

Başlık, virgülle ayrılmış bir veya birden fazla yönerge taşır. Yönergeler büyük küçük harfe duyarlı değildir, ancak bazı uygulamalar büyük harfli yazımı tanımadığı için küçük harf önerilir. Argüman alan yönergelerde değer eşittir işaretiyle verilir ve genellikle tam sayı olduğu için tırnak içine alınmaz.
Cache-Control: max-age=180, public
Cache-Control: no-cache
Cache-Control: max-age=604800, stale-while-revalidate=86400Aynı başlık hem istekte hem yanıtta kullanılabilir, fakat yönergelerin bir kısmı yalnızca bir tarafta anlam taşır. Aşağıdaki tablo MDN'in yönerge listesini özetler. Tanımadığı yönergeyi gören bir istemcinin onu yok sayması beklenir; tarayıcı desteği için MDN uyumluluk tablosuna bakın.
| Yönerge | Yanıtta | İstekte |
|---|---|---|
| max-age=N | Yanıt üretildikten sonra N saniye taze | En fazla N saniyelik yanıtı kabul ederim |
| s-maxage=N | Yalnızca paylaşılan önbellek için tazelik süresi | Yok |
| no-cache | Saklanabilir, her kullanımdan önce doğrulanmalı | Önbellekten önce sunucuya doğrulat |
| no-store | Hiçbir önbellek saklamamalı | Bu isteği ve yanıtı saklama |
| must-revalidate | Bayatlayınca doğrulanmadan kullanılamaz | Yok |
| proxy-revalidate | must-revalidate, yalnızca paylaşılan önbellek için | Yok |
| private | Yalnızca özel (tarayıcı) önbellekte saklanabilir | Yok |
| public | Authorization olsa bile paylaşılan önbellekte saklanabilir | Yok |
| immutable | Tazeyken içerik değişmeyecek, yeniden doğrulama gerekmez | Yok |
| stale-while-revalidate=N | Bayatladıktan sonra N saniye arka planda doğrulanırken kullanılabilir | Yok |
| stale-if-error=N | 500, 502, 503, 504 hatasında N saniye bayat kopya kullanılabilir | Tarayıcılar desteklemiyor |
| no-transform | Ara katman içeriği dönüştürmemeli | Aynı anlam |
| max-stale, min-fresh | Yok | Bayat veya en az N saniye taze yanıt isteği |
| only-if-cached | Yok | Yalnızca önbellekteki kopyayı ver, yoksa 504 |
Taze ve bayat: tazelik nasıl hesaplanır?
Saklanan bir yanıt ya taze (fresh) ya da bayat (stale) durumdadır. Taze yanıt sunucuya sorulmadan yeniden kullanılır; bayat yanıt ise olduğu gibi kullanılamaz, ama hemen silinmesi de gerekmez, çünkü doğrulama sonrasında yeniden taze hale gelebilir. Ölçüt yaştır: HTTP'de yaş, yanıtın kaynak sunucuda üretilmesinden bu yana geçen süredir.
Burada sık atlanan bir ayrıntı var: max-age yanıtın tarayıcıya ulaştığı andan değil, kaynak sunucuda üretildiği andan itibaren sayılır. Yoldaki bir paylaşılan önbellek yanıtı bir gün tutmuşsa bunu Age başlığıyla bildirir ve tarayıcı bu süreyi kendi tazelik ömründen düşer. MDN'in örneğinde bir haftalık max-age=604800 ile gelen ve Age: 86400 taşıyan yanıt, istemci için kalan 518400 saniye boyunca tazedir.
HTTP/1.1 200 OK
Content-Type: text/html
Date: Tue, 22 Feb 2022 22:22:22 GMT
Cache-Control: max-age=604800
Age: 86400Bu hesabı tarayıcıda da Node.js'te de aynı çalışan Response ve Headers nesneleriyle küçük bir yardımcıya dönüştürebilirsiniz. Aşağıdaki kod yönergeleri küçük harfe çevirerek ayrıştırır ve kalan tazelik süresini hesaplar. Bu basitleştirilmiş bir öğretim örneğidir; gerçek önbelleklerin uyguladığı tüm kuralları (örneğin sezgisel önbelleklemeyi) içermez.
function yonergeler(deger) {
const sonuc = {};
for (const parca of deger.split(',')) {
const [ad, arguman] = parca.trim().toLowerCase().split('=');
if (ad) sonuc[ad] = arguman === undefined ? true : Number(arguman);
}
return sonuc;
}
function kalanTazelik(yanit) {
const cc = yonergeler(yanit.headers.get('Cache-Control') ?? '');
const yas = Number(yanit.headers.get('Age') ?? 0);
if (cc['no-store'] || cc['no-cache'] || cc['max-age'] === undefined) return 0;
return Math.max(0, cc['max-age'] - yas);
}
const yanit = new Response('...', {
headers: { 'Cache-Control': 'Max-Age=604800, Public', Age: '86400' },
});
console.log(JSON.stringify(yonergeler(yanit.headers.get('Cache-Control'))));
// {"max-age":604800,"public":true}
console.log(kalanTazelik(yanit)); // 518400
console.log(kalanTazelik(new Response('', { headers: { 'Cache-Control': 'no-cache' } }))); // 0max-age değeri negatifse (örneğin -1) ya da tam sayı değilse (örneğin 3599.99) davranış belirtimde tanımsızdır ve önbelleklerin bunu 0 gibi yorumlaması teşvik edilir. Yani ondalıklı bir değer yazarak "biraz daha uzun" süre elde edemezsiniz.
Expires ve sezgisel önbellekleme
HTTP/1.0 döneminde tazelik Expires başlığına yazılan mutlak bir tarihle belirtiliyordu. Tarih biçiminin ayrıştırılması zor olduğu ve sistem saatiyle oynanarak sorun çıkarılabildiği için HTTP/1.1, geçen süreye dayanan max-age yönergesini getirdi. Yanıtta max-age veya s-maxage varsa Expires yok sayılır; bu nedenle bugün ikisini birlikte göndermenin pratik bir getirisi kalmamıştır.
Hiç Cache-Control göndermemek "önbellekleme" anlamına gelmez. HTTP mümkün olduğunca önbelleklemek üzere tasarlandığından, yönerge olmayan bir yanıt da belirli koşullarda saklanıp kullanılabilir; buna sezgisel önbellekleme (heuristic caching) denir. Örneğin bir yıldır değişmemiş bir yanıt için belirtim, saklandıktan sonraki sürenin yaklaşık yüzde 10'u kadar yeniden kullanmayı önerir; kesin süre uygulamaya bağlıdır. MDN bu yüzden her yanıta açıkça bir Cache-Control vermenizi tavsiye eder.
no-cache ile no-store farkı
Adı yanıltıcı olduğu için en çok karıştırılan yönerge no-cache'tir. no-cache "önbelleğe alma" demek değildir: yanıt saklanabilir, ama her yeniden kullanımdan önce kaynak sunucuyla doğrulanmalıdır, önbellek sunucuya erişemiyor olsa bile. İçerik her seferinde güncel olsun ama değişmediyse yeniden indirilmesin istiyorsanız doğru yönerge budur. Sunucu koşullu istekleri destekliyorsa çoğu zaman gövdesiz bir 304 döner ve trafik çok küçük kalır.
no-store ise hiçbir önbelleğin, özel ya da paylaşılan, yanıtı saklamaması gerektiğini söyler. MDN iki önemli uyarı yapar. Birincisi, no-store aynı URL için daha önce saklanmış eski bir yanıtı silmez; yani eski kopya kullanılmaya devam edebilir, oysa no-cache her kullanımdan önce doğrulamayı zorunlu kılar. İkincisi, no-store'u gelişigüzel kullanmak tarayıcının geri/ileri önbelleği (bfcache) dahil birçok avantajı kaybettirir. Kişisel içerik için MDN'in önerisi çoğu durumda no-cache, private birleşimidir.
| Amaç | Önerilen değer | Neden |
|---|---|---|
| Her zaman güncel içerik | no-cache | Saklar ama her kullanımda doğrular, değişmediyse 304 |
| Kişisel sayfa, başkasına gitmesin | no-cache, private | Paylaşılan önbellek saklamaz, tarayıcı doğrular |
| Hiçbir yerde saklanmasın | no-store | Hiçbir önbellek saklamaz, bfcache gibi avantajlar kaybolur |
| Sürümlü statik dosya | max-age=31536000, immutable | URL değişmedikçe içerik değişmez |
Eski uygulamalarla başa çıkmak için görebileceğiniz no-store, no-cache, max-age=0, must-revalidate, proxy-revalidate gibi "her şey dahil" başlıklar, MDN'e göre çakışan yönergeler içerir; çakışmada en kısıtlayıcı olan geçerli sayıldığından pratikte no-store ile eşdeğerdir. Benzer şekilde max-age=0, must-revalidate birleşimi HTTP/1.0 dönemindeki önbelleklerin no-cache'i anlamamasına karşı geliştirilmiş bir geçici çözümdür; bugün doğrudan no-cache yazmanız yeterlidir.
private, public ve s-maxage
private, yanıtın yalnızca özel önbellekte saklanabileceğini söyler. Oturum açmış kullanıcının panosu, sepeti veya profil API'si gibi içerikler için zorunlu kabul edilmelidir. Paylaşılan önbelleklerdeki istek birleştirme (request collapse) da bu yönergeyle ilgilidir: aynı anda gelen özdeş istekleri önbellek tek istek halinde kaynağa iletip sonucu herkese dağıtabilir. MDN, bunun yanıt max-age=0 veya no-cache taşısa bile gerçekleşebileceğini, kişiye özel yanıtın birleştirmede paylaşılmaması için private eklenmesi gerektiğini belirtir.
public sanıldığı kadar sık gerekmez. Normalde Authorization başlığıyla yapılan isteklerin yanıtları paylaşılan önbellekte saklanmaz; public bu kısıtı kaldırır. İstekte Authorization yoksa ya da yanıtta zaten s-maxage veya must-revalidate varsa (bunlar da kısıtı kaldırır) public eklemeye gerek yoktur. Temel kimlik doğrulamayla kişiselleştirilmiş yanıtlarda public kullanmak ise sorun çıkarabilir.
s-maxage yalnızca paylaşılan önbellekler için tazelik süresi verir; özel önbellekler onu yok sayar, paylaşılan önbelleklerde ise max-age ve Expires değerinin önüne geçer. Böylece tarayıcının kısa, CDN'in daha uzun süre tutmasını tek başlıkta ifade edebilirsiniz.
immutable, stale-while-revalidate ve stale-if-error
immutable, yanıtın taze kaldığı sürece güncellenmeyeceğini bildirir. Kullanıcı sayfayı yenilediğinde tarayıcı normalde koşullu doğrulama istekleri gönderir; içeriği asla değişmeyen, adında sürüm veya özet (hash) taşıyan dosyalar için bu istekler gereksizdir ve immutable onları önler. MDN ayrıca Chrome'un bu yönergeyi uygulamak yerine yenilemede alt kaynakları doğrulamayacak şekilde davranışını değiştirdiğini not eder.
stale-while-revalidate=N, yanıt bayatladıktan sonraki N saniye boyunca önbelleğin onu kullanmaya devam edip arka planda doğrulamasına izin verir. max-age=604800, stale-while-revalidate=86400 değeri yanıtı yedi gün taze tutar, sonraki bir gün içinde gelen istekler bayat kopyayla hemen karşılanırken önbellek arka planda tazeler. O bir günlük pencerede hiç istek gelmezse bir sonraki istek normal doğrulamayla yapılır. stale-if-error=N ise sunucu 500, 502, 503 veya 504 döndürdüğünde bayat kopyanın N saniye daha kullanılmasına izin verir; süre dolunca istemci hatayı görür.
must-revalidate bunun tersi yönde çalışır. HTTP, kaynak sunucuya ulaşılamadığında önbelleklerin bayat yanıtı kullanmasına izin verir; must-revalidate bunu yasaklar ve ya doğrulama yapılır ya da 504 (Gateway Timeout) üretilir. Genellikle max-age ile birlikte yazılır.
Vary: önbellek anahtarına başlık eklemek
Önbellekler yanıtları temelde URL'ye göre ayırır. Ancak içerik pazarlığı yapan bir sunucuda aynı URL, Accept-Language veya Accept-Encoding değerine göre farklı gövde döndürebilir. Vary başlığı, yanıtı etkileyen istek başlıklarını listeler ve önbellek anahtarını URL ile bu başlıkların birleşimine çevirir. Böylece Türkçe için saklanmış bir yanıt, İngilizce isteyen kullanıcıya sunulmaz.
HTTP/1.1 200 OK
Content-Language: tr
Vary: Accept-Language
Cache-Control: max-age=3600MDN üç uyarı yapar. Aynı URL'nin tüm yanıtlarında, 304 dahil, aynı Vary değeri kullanılmalıdır. Vary: User-Agent çok fazla farklı değer ürettiği için önbellekten yararlanma olasılığını ciddi biçimde düşürür; mümkünse kullanıcı ajanı yerine özellik algılamaya dayanın. Kişisel içeriğin başkalarına gitmemesi için çerezi Vary'e eklemek yerine Cache-Control: private kullanın. Vary: * ise yanıtın istek başlıkları dışındaki etkenlere bağlı olduğunu, yani önbelleklenemez olduğunu belirtir.
Koşullu istekler: ETag, Last-Modified ve 304

Bayatlayan yanıt atılmaz; tarayıcı onu bir koşullu istekle sunucuya sorar. Bunun için iki tür doğrulayıcı vardır. Last-Modified, sunucunun kaynağın en son değiştiğine inandığı tarihi GMT olarak taşır. ETag ise belirli bir sürümü tanımlayan, çift tırnak içinde opak bir ASCII dizesidir; nasıl üretileceği belirtilmemiştir, genellikle içeriğin özeti, değişiklik zamanının özeti ya da bir revizyon numarasıdır. Kaynak değiştiğinde yeni bir ETag üretilmesi zorunludur.
Tarayıcı, sakladığı ETag değerini If-None-Match başlığına, Last-Modified değerini If-Modified-Since başlığına koyar. Sunucu güncel sürümün etiketi eşleşiyorsa ya da kaynak o tarihten beri değişmediyse gövdesiz 304 Not Modified döner; yanıt yeniden taze sayılır ve kalan süre boyunca kullanılır. Kaynak değiştiyse normal bir 200 OK ve yeni gövde gelir.
GET /index.html HTTP/1.1
Host: example.com
If-None-Match: "33a64df5"
If-Modified-Since: Tue, 22 Feb 2022 22:00:00 GMT
HTTP/1.1 304 Not Modified
Date: Tue, 22 Feb 2022 23:22:22 GMT
ETag: "33a64df5"
Cache-Control: max-age=3600İki başlık birlikte gelirse sunucu destekliyorsa If-None-Match önceliklidir ve If-Modified-Since yok sayılır. If-Modified-Since yalnızca GET ve HEAD ile kullanılabilir. 304 yanıtı gövde içermemeli, eşdeğer bir 200 yanıtında gönderilecek Cache-Control, Content-Location, Date, ETag, Expires ve Vary başlıklarını taşımalıdır. Diğer durum kodlarının anlamları için HTTP durum kodları yazısına bakın.
Aşağıdaki örnek, bir sunucunun bu kararı nasıl verdiğini yerel Request ve Response nesneleriyle canlandırır. ETag, gövdenin SHA-256 özetinden crypto.subtle.digest ile üretilir; ilk istek 200 alır, etiketi If-None-Match ile geri gönderen ikinci istek gövdesiz 304 alır. Kod ağ isteği yapmaz; tarayıcıda da geçerlidir.
const govde = '<!doctype html><title>Merhaba</title>';
async function etagHesapla(metin) {
const veri = new TextEncoder().encode(metin);
const ozet = await crypto.subtle.digest('SHA-256', veri);
const hex = Array.from(new Uint8Array(ozet), (b) => b.toString(16).padStart(2, '0')).join('');
return '"' + hex.slice(0, 16) + '"';
}
async function yanitla(istek) {
const etag = await etagHesapla(govde);
const ortak = { 'Cache-Control': 'no-cache', ETag: etag };
if (istek.headers.get('If-None-Match') === etag) {
return new Response(null, { status: 304, headers: ortak });
}
return new Response(govde, { status: 200, headers: { ...ortak, 'Content-Type': 'text/html' } });
}
const ilk = await yanitla(new Request('https://example.com/'));
console.log(ilk.status, ilk.headers.get('ETag')); // 200 "a69080e5ec424971"
const ikinci = await yanitla(new Request('https://example.com/', {
headers: { 'If-None-Match': ilk.headers.get('ETag') },
}));
console.log(ikinci.status, (await ikinci.text()).length); // 304 0Gerçek bir sunucuda karşılaştırma bu kadar basit değildir: If-None-Match birden fazla etiket veya * içerebilir ve zayıf karşılaştırma kullanır. Request, Response ve gövde yöntemlerinin ayrıntıları için Request, Response ve Headers yazısına, crypto.subtle.digest için Web Crypto API yazısına bakın.
Güçlü ve zayıf doğrulama
Güçlü doğrulama iki sürümün bayt bayt aynı olmasını şart koşar; yarıda kalan bir indirmeyi sürdürürken gereken budur. Zayıf doğrulama ise içeriğin anlamca eşdeğer olmasını yeterli görür; örneğin yalnızca alt bilgideki tarihi veya reklamı farklı iki sayfa aynı sayılabilir. Zayıf etiketler W/ önekiyle yazılır (büyük küçük harfe duyarlıdır). If-None-Match her zaman zayıf karşılaştırma yapar; If-Match güçlü karşılaştırma yapar ve W/ önekli etiketleri hiçbir zaman eşleştirmez. MDN ayrıca sıkıştırma yapan bazı ters proxy'lerin, içerik kodlaması değiştiği için ETag değerini değiştirdiğini not eder.
Kayıp güncelleme sorununu önlemek
Koşullu istekler yalnızca önbellek için değildir. İki kullanıcı aynı belgeyi açıp düzenlediğinde, sonra kaydeden diğerinin değişikliğini fark etmeden ezer. İyimser kilitleme bunu çözer: istemci PUT veya POST isteğine okuduğu sürümün etiketini If-Match ile ekler; arada belge değiştiyse sunucu 412 Precondition Failed döndürür ve istemci kullanıcıyı uyarır. İlk yükleme için If-None-Match: * kullanılır; istek yalnızca kaynak daha önce yoksa başarılı olur.
PUT /wiki/sayfa HTTP/1.1
Host: example.com
If-Match: "33a64df551425fcc55e4d42a148795d9f25f89d4"
Content-Type: text/plain
yeni içerikTarayıcıdan önbelleği yönetmek: fetch cache seçeneği
Sayfa kodunuz da HTTP önbelleğiyle etkileşimi seçebilir. fetch() çağrısındaki cache seçeneği Request.cache değerini belirler. MDN'e göre normal bir yenilemenin karşılığı no-cache modudur (önbellekte kopya varsa koşullu istek yapılır), zorla yenilemenin karşılığı ise reload modudur (önbelleğe bakmadan indirir, sonra önbelleği günceller). no-store önbelleğe hiç bakmaz ve onu güncellemez; force-cache bayat olsa bile kopyayı kullanır; only-if-cached yalnızca mode: 'same-origin' ile kullanılabilir.
// normal yenileme gibi: kopya varsa koşullu istek gönderir
fetch('/api/ayarlar', { cache: 'no-cache' });
// zorla yenileme gibi: önbelleğe bakmaz, sonucu önbelleğe yazar
fetch('/api/ayarlar', { cache: 'reload' });
// önbelleği hiç kullanmaz ve güncellemez
fetch('/api/ayarlar', { cache: 'no-store' });Fetch seçeneklerinin tamamı Fetch API kullanımı yazısında, service worker ile kendi önbellek mantığınızı kurmak ise service worker önbellek stratejileri ve Cache API yazılarında anlatılıyor. Cache API, HTTP önbelleğinden ayrı bir depodur ve Cache-Control başlıklarına uymaz.
Çoğu siteye yeten iki desen
MDN, sitelerin büyük bölümünün iki desenle karşılanabileceğini söyler. Birincisi önbellek kırma (cache busting): JavaScript, CSS ve görseller gibi alt kaynakların URL'sine sürüm numarası veya içerik özeti eklenir (bundle.v123.js ya da bundle.js?v=123). İçerik değiştiğinde URL de değiştiği için eski kopya hiç kullanılmaz; bu yüzden bu dosyalara çok uzun bir max-age ve immutable verilebilir. Last-Modified ve ETag eklemek de yenilemede gereksiz aktarımı önler.
İkincisi ana kaynaklardır: HTML belgesinin URL'si süslenemez, bu yüzden önbellek kırma uygulanamaz. HTML için no-store değil no-cache uygundur; doğrulayıcılarla birlikte gönderildiğinde içerik değişmediyse 304 döner. Oturum açılmış, çerezle kişiselleştirilmiş HTML için private eklenir. Aynı yaklaşım favicon.ico, manifest.json, .well-known ve URL'si değiştirilemeyen API uç noktaları için de geçerlidir.
# /assets/app.3f9a1c.js
Cache-Control: max-age=31536000, immutable
ETag: "3f9a1c"
# /index.html (herkese aynı)
Cache-Control: no-cache
Last-Modified: Tue, 22 Feb 2022 20:20:20 GMT
ETag: "AAPuIbAOdvAGEETbgAAAAAAABAAE"
# /hesabim (oturum açmış kullanıcı)
Cache-Control: no-cache, privateMDN, max-age süresi olarak bir hafta, bir ay veya bir yıl gibi QPACK tablosunda önceden tanımlı değerleri seçmenin HTTP/3'te başlığı tek baytla sıkıştırmaya imkan verdiğini, ama önbellekler yeni kayıt geldikçe eskileri sildiği için pratikte bu seçimin büyük fark yaratmadığını belirtir. Kimlik doğrulamalı kişisel yanıtlardan emin değilseniz public içermeyen max-age=2592000 (bir ay) daha güvenli bir seçimdir.
Saklanmış yanıtı silmek mümkün mü?
Uzun bir max-age ile ara sunuculara dağılmış bir yanıtı standart yönergelerle silmenin yolu yoktur; önbellek yanıtı tuttukça istek size hiç ulaşmaz. Clear-Site-Data: cache başlığı tarayıcı önbelleğini temizleyebilir ama paylaşılan ve ara önbellekleri etkilemez; ayrıca sitenin tarayıcıdaki tüm saklı yanıtlarını sildiği için dikkatli kullanılmalıdır. CDN gibi yönetilen önbellekler panel veya API üzerinden temizleme sunabilir. Sık güncellenen bir URL'nin kontrolünü kaybetmek istemiyorsanız MDN'in önerisi no-cache kullanmaktır.
Sık yapılan hatalar

- Önbelleği kapatmak için no-cache yazmak.
no-cachesaklamayı engellemez; saklanmasın istiyorsanızno-storekullanın. - Kişisel yanıtta private unutmak. Oturum sonrası içerik paylaşılan önbelleğe düşüp başka kullanıcılara sunulabilir.
- Hiç Cache-Control göndermemek. Sezgisel önbellekleme devreye girer ve yanıt beklemediğiniz kadar saklanabilir.
- Sürümsüz dosyaya uzun max-age vermek.
/app.jsbir yıl saklanırsa yeni sürümü yayınlasanız da kullanıcı eskisini görür. Uzun süre yalnızca önbellek kırma ile birlikte kullanılmalı. - Vary değerini yanıtlar arasında değiştirmek. 304 dahil tüm yanıtlarda aynı olmalı.
- Her yere public eklemek. Yalnızca
Authorizationbaşlıklı yanıtların paylaşılan önbellekte saklanması gerektiğinde lazımdır. - Geliştirici araçlarındaki 304'lere takılmak. MDN, bazı ağ panellerinin yerel önbellek erişimini görünür kılmak için ek istekler ve 304 yanıtları gösterebildiğini not eder.
Sık Sorulan Sorular
Cache-Control: no-cache sayfanın hiç önbelleğe alınmamasını sağlar mı?
Hayır. Yanıt saklanır, ancak her kullanımdan önce sunucuyla doğrulanır. Hiç saklanmamasını istiyorsanız no-store kullanmanız gerekir; ama MDN bunun bfcache gibi avantajları kaybettireceğini hatırlatır.
ETag mi Last-Modified mi kullanmalıyım?
MDN mümkünse ikisini birlikte göndermenizi önerir. Doğrulamada ikisi de geldiğinde If-None-Match önceliklidir; Last-Modified ise CMS'lerin değişiklik tarihini göstermesi ve tarayıcıların sezgisel önbelleklemesi gibi başka amaçlara da hizmet eder.
304 yanıtı neden gövde içermez?
304, istemcideki kopyanın hâlâ geçerli olduğunu bildirir; gövdeyi yeniden göndermek gereksiz olur. Yanıt yalnızca eşdeğer 200 yanıtındaki önbellek başlıklarını taşır ve istemci sakladığı gövdeyi kullanır.
s-maxage ile max-age birlikte yazılırsa ne olur?
Tarayıcı gibi özel önbellekler s-maxage değerini yok sayar ve max-age değerine uyar. CDN ve proxy gibi paylaşılan önbelleklerde ise s-maxage önceliklidir.
Kullanıcının tarayıcısındaki eski kopyayı nasıl silerim?
Önce kopyanın uzun süre saklanmasını önleyen başlıkları seçmek gerekir. Zaten saklanmışsa Clear-Site-Data: cache tarayıcı önbelleğini temizleyebilir; CDN gibi ara katmanlar için ise ürünün temizleme aracını kullanmanız gerekir.
Marka adları sahiplerine aittir. Bu yazı bağımsız bir teknik rehberdir; adı geçen kuruluşlarla bayilik veya ortaklık ilişkisi bulunduğu anlamına gelmez.
İlgili içerikler: Web API öğrenme rehberi · Önbellek nedir · HTTP durum kodları · HTTP istek ve yanıt yapısı · Request, Response ve Headers · Service worker önbellek stratejileri · Cache API