Cache ve Doğrulama

ETag mi Last-Modified mı?

ETag token ve zaman damgası doğrulama akışlarını karşılaştıran; 304 yanıtı ve koşullu istek mekanizmasını gösteren teknik diyagram

Cache'te saklanan bir kaynağın süresi dolduğunda tarayıcı iki yol arasında seçim yapar. Birincisi kaynağı geçersiz sayıp tam bir yeniden indirme başlatmaktır. İkincisi — ve çok daha verimli olanı — elindeki kaynağın hâlâ geçerli olup olmadığını sunucuya sormaktır. Bu soru iki farklı header aracılığıyla iletilir: biri zamana dayalı, diğeri içeriğe dayalı.

Last-Modified, kaynağın en son ne zaman değiştirildiğini taşır. ETag, kaynağın belirli bir versiyonunu temsil eden benzersiz bir tanımlayıcıdır. Her ikisi de aynı hedefe yönelir: içerik değişmemişse tam aktarımdan kaçınmak, yalnızca küçük bir doğrulama isteğiyle "hâlâ geçerli" onayını almak.

Ancak bu benzerlik yüzeyseldir. Zaman damgasına dayalı doğrulama bazı ortamlarda sessiz sedasız başarısız olur. ETag ise her koşulda güvenilir değildir — yanlış yapılandırıldığında sorunu çözmek yerine büyütür. Hangisinin ne zaman tercih edileceğini anlamak, bu mekanizmaların nasıl çalıştığını ve nerede kırıldığını görmekle başlar.

Koşullu istek mekanizması ve doğrulama mantığı

Bir kaynak için Cache-Control direktifindeki max-age süresi dolduğunda kaynak geçersiz sayılır, ama tarayıcı cache'ten silinmez. Tarayıcı bu kaynağı elinde tutar ve bir doğrulama isteği gönderir. Bu isteğin içeriği basittir: "Bende X versiyonu var, hâlâ geçerli mi?" Sunucu içeriği inceleyip yanıtlar.

Doğrulama başarılıysa — yani kaynak değişmemişse — sunucu 304 Not Modified yanıtı döner. Body yoktur, yalnızca birkaç header satırı gelir. Tarayıcı elindeki kaynağın geçerliliği uzatılmış sayıldığını anlayarak onu kullanmaya devam eder. İçerik değişmişse 200 yanıtıyla yeni versiyon gelir ve cache güncellenir. Bu mekanizma, cache miss'in tam aktarım maliyetini önlemek için tasarlanmıştır.

304 Not Modified yanıtının performans değeri

304 yanıtının asıl kazancı içerik transferini ortadan kaldırmasıdır. Büyük bir görsel, kapsamlı bir CSS dosyası ya da çok kez yüklenen bir JavaScript bundle — bunların TTL'i dolduğunda yeniden tam aktarım başlatmak yerine doğrulama isteği göndermek bant genişliğini önemli ölçüde korur. Sunucu yalnızca birkaç onlarca byte'lık header döndürür; tarayıcı kendi cache'ini kullanmaya devam eder.

Tekrarlayan ziyaretlerde bu kazanç çarpıcı hale gelir. Kullanıcı bir sayfaya geri döndüğünde cache'teki kaynakların büyük bölümü hâlâ doğrulanabilir durumdadır. Her biri için tam indirme yerine doğrulama isteği gidip 304 geliyorsa, sayfanın yeniden yüklenme hızı yeni bir ziyaretçiye kıyasla çok daha yüksektir. TTFB bağlamında bu yalnızca küçük bir doğrulama gecikmesi ekler; içerik yeniden aktarılmaz.

Last-Modified nasıl çalışır

Sunucu bir kaynak gönderirken yanıta Last-Modified: Tue, 15 Apr 2026 10:30:00 GMT ekleyebilir. Bu değer dosyanın dosya sistemindeki son değiştirilme zamanını taşır. Tarayıcı bu değeri o kaynakla birlikte saklar.

Bir sonraki doğrulama isteğinde bu zaman damgası If-Modified-Since: Tue, 15 Apr 2026 10:30:00 GMT header'ı olarak sunucuya iletilir. Sunucu, kaynağın mevcut son değiştirilme zamanını bu değerle karşılaştırır. Dosya o tarihten bu yana değişmemişse 304 döner. Değişmişse yeni içerik ve güncellenmiş Last-Modified değeriyle 200 gelir. Mekanizma sade ve HTTP'nin ilk versiyonlarından bu yana destekleniyor; bu yüzden uyumluluk açısından son derece geniş bir tabana sahip.

Zaman damgası doğrulamasının sınırları

Last-Modified'ın zaman damgasına bağımlılığı belirli durumlarda sorun yaratır. Birincisi granularite sorunudur: Last-Modified değeri saniye düzeyinde çalışır. Aynı saniye içinde iki kez güncellenen bir dosya bu iki değişikliği ayrı ayrı temsil edemez. Sunucu, dosyanın değiştiğini fark etmeden 304 döndürebilir.

İkincisi dosya sistemi kaynaklı tutarsızlıklardır. Bir dosyanın içeriği değişmeden yalnızca meta verisi güncellendiğinde — örneğin touch komutuyla zaman damgası yenilendiğinde — Last-Modified değeri değişir ve sunucu gereksiz yere tam içerik gönderir. Tersine, bazı build sistemleri dosyaları yeniden üretirken orijinal zaman damgasını bilinçli olarak korur; içerik değişmiş olsa bile sunucu 304 döndürebilir. Bu durum kullanıcının eski içeriği görmeye devam etmesi anlamına gelir.

Üçüncüsü çok sunuculu ortamlardır. Load balancer arkasında birden fazla web sunucusu varsa, aynı dosyanın farklı sunucularda farklı zaman damgaları taşıması mümkündür. Kullanıcının isteği her seferinde farklı bir sunucuya gidebilir; bu durumda doğrulama tutarsız sonuçlar üretir.

ETag nedir, nasıl üretilir

ETag (Entity Tag), bir kaynağın belirli bir versiyonunu temsil eden tanımlayıcıdır. Sunucu yanıta ETag: "a3f8b2c1d9e4" gibi tırnak içinde bir değer ekler. Bu değer genellikle içeriğin hash'inden ya da inode numarası, dosya boyutu ve son değiştirilme zamanının birleşiminden türetilir.

Üretim yöntemi sunucudan sunucuya farklılaşır. Apache varsayılan olarak inode numarasını, boyutu ve son değiştirilme zamanını kullanır. Nginx son değiştirilme zamanı ile içerik boyutunu birleştirir. Uygulama katmanında üretilen ETag'ler ise doğrudan içerik hash'ini kullanabilir; bu yöntem sunucu konfigürasyonundan bağımsız olduğu için en tutarlı sonucu verir. Hangi yöntem kullanılırsa kullanılsın, içerik değiştiğinde ETag değişmeli; değişmediğinde aynı kalmalıdır.

Güçlü ve zayıf ETag arasındaki fark

ETag değerleri iki biçimde gelir. Güçlü ETag ("a3f8b2c1") byte-for-byte özdeşliği garanti eder. Aynı güçlü ETag'e sahip iki yanıt birbiriyle tam olarak aynıdır; tek bir byte dahi farklıysa ETag değerinin de farklı olması gerekir. Bu katı tanım, Range isteklerinde ve kısmi içerik doğrulamasında gereklidir.

Zayıf ETag ise W/"a3f8b2c1" biçiminde belirtilir ve semantik eşdeğerliği ifade eder. İki yanıt anlam olarak aynı içeriği sunuyor olabilir ama byte düzeyinde farklılıklar barındırabilir. Bu durum örneğin sıkıştırma yönteminin veya başlık içeriğinin farklılaştığı durumlarda ortaya çıkabilir. Zayıf ETag yalnızca tam kaynak doğrulamasında kullanılabilir; kısmi içerik istekleriyle birleştirilemez.

If-None-Match ile doğrulama akışı

Tarayıcı bir kaynağa ait ETag'i sakladıktan sonra, doğrulama isteğinde If-None-Match: "a3f8b2c1" header'ı olarak sunucuya iletir. Sunucu bu değeri kaynağın mevcut ETag'iyle karşılaştırır. Değerler eşleşiyorsa içerik değişmemiştir; 304 yanıtı döner. Eşleşmiyorsa kaynak değişmiştir; 200 yanıtıyla yeni içerik ve güncellenmiş ETag değeri gelir.

Birden fazla ETag değeri tek bir If-None-Match header'ında gönderilebilir: If-None-Match: "etag-a", "etag-b". Sunucu bunlardan herhangi biriyle eşleşiyorsa 304 döner. Bu özellik, istemcinin birden fazla olası versiyon için önbellekte saklanan değerleri tek bir istekte doğrulayabilmesine imkân tanır. Pratikte çoğu tarayıcı en son saklanan tek ETag değerini gönderir; birden fazla değer gönderme daha çok API istemcilerinde veya özel cache implementasyonlarında karşılaşılır.

ETag'in Last-Modified'a göre öne çıktığı durumlar

Sub-second değişiklikler ETag'in en açık üstünlük alanıdır. Aynı saniye içinde iki kez güncellenen bir kaynak için Last-Modified her iki versiyonu da aynı zaman damgasıyla temsil eder; sunucu değişikliği fark edemez. ETag ise içerik değiştiğinde farklı bir değer üretir; bu fark her zaman tespit edilir.

Load balancer arkasında birden fazla sunucu olduğunda da ETag daha güvenilir bir seçenektir — ama yalnızca doğru yapılandırıldığında. Eğer her sunucu içerik hash'ini kullanarak ETag üretiyorsa aynı dosya için tüm sunucular aynı değeri üretir. Kullanıcının isteği hangi sunucuya giderse gitsin, doğrulama tutarlı çalışır ve gereksiz 200 yanıtları önlenir.

Last-Modified'ın hâlâ geçerli olduğu durumlar

ETag her koşulda üstün değildir. Tek bir sunucudan statik dosya sunan, yapılandırması karmaşık olmayan ortamlarda Last-Modified yeterlidir. Ek yapılandırma gerektirmez; Apache ve Nginx başta olmak üzere çoğu web sunucusu varsayılan olarak gönderir. CDN'lerin büyük bölümü de Last-Modified'ı anlayıp doğrulama sürecine dahil eder.

Bazı eski proxy ve CDN'ler ETag'i ya desteklemez ya da koşullu isteği origin'e iletmeden doğrular. Bu ortamlarda Last-Modified daha geniş uyumluluk sağlar. Ayrıca Last-Modified insan tarafından okunabilir bir tarih-saat değeri taşıdığından log incelemesi ve hata ayıklama süreçlerinde pratik bir avantaj sunar.

Her ikisi birlikte gönderildiğinde ne olur

Sunucular sıklıkla her iki header'ı da yanıta ekler: hem ETag hem de Last-Modified. HTTP spesifikasyonuna göre istemci her ikisini de saklamalı ve doğrulama isteğinde If-None-Match ve If-Modified-Since header'larını birlikte göndermelidir.

Peki sunucu bu iki koşulu nasıl ele alır? RFC 7232'ye göre sunucu If-None-Match mevcut olduğunda önce onu değerlendirmelidir. If-None-Match eşleşiyorsa 304 döner, If-Modified-Since kontrolü atlanır. If-None-Match eşleşmiyorsa 200 ile tam içerik döner — yine If-Modified-Since incelenmez. If-None-Match header'ı hiç gönderilmemişse ancak o zaman If-Modified-Since devreye girer. Bu hiyerarşi, ETag'in otomatik olarak öncelik kazandığı anlamına gelir. İki header bir arada gönderildiğinde ETag kazanır.

Sunucu yapılandırmalarının ETag üretimine etkisi

Apache varsayılan yapılandırmasında ETag'i inode numarası, dosya boyutu ve son değiştirilme zamanından türetir. Tek sunuculu ortamlarda bu makul çalışır. Ama çok sunuculu yapılarda inode numaraları dosya sistemine özgüdür — aynı dosya farklı sunucularda farklı inode değerleri alır. Sonuç: her sunucu farklı ETag üretir, doğrulama her seferinde başarısız olur ve gereksiz 200 yanıtları artar.

Apache'de bu sorunu gidermek için FileETag MTime Size direktifiyle inode bileşeni dışarıda bırakılabilir. Nginx inode kullanmadığı için bu sorunla daha az karşılaşılır; ama yine de son değiştirilme zamanındaki milisaniye tutarsızlıkları farklı değerler üretebilir. En tutarlı çözüm, uygulama katmanında içerik hash'i tabanlı ETag üretmektir. Bu yaklaşım sunucu konfigürasyonuna bağımlılığı ortadan kaldırır ve içerik değişmediği sürece her ortamda aynı değeri üretir.

CDN ve proxy'lerin koşullu isteği işleme biçimi

CDN'lerin koşullu isteklere yaklaşımı sağlayıcıdan sağlayıcıya değişir. Bazı CDN'ler If-None-Match isteğini kendi cache'indeki ETag ile doğrudan karşılayabilir — istek origin'e hiç ulaşmaz. Bu durum hem origin yükünü hem de gecikmeyi minimize eder. Diğerleri koşullu isteği origin'e iletir; origin 304 döndürdüğünde CDN bu bilgiyi kaydeder ve cache'ini günceller.

CDN'nin ETag değerini dönüştürüp dönüştürmediği de önemli bir ayrıntıdır. Bazı CDN'ler sıkıştırılmış ve sıkıştırılmamış versiyonlar için farklı ETag değerleri üretir. Tarayıcı sıkıştırılmış versiyonun ETag'ini saklarken CDN orijinal içeriğin ETag'ini iletiyorsa eşleşme sağlanamaz; gereksiz tam aktarımlar tetiklenir. Bu dönüşümleri anlamak için CDN yanıt header'larını incelemek ve ETag değerinin hangi katmanda üretildiğini netleştirmek gerekir.

Pratikte tercih: hangi senaryo hangisini gerektirir

Tek sunucudan statik dosya sunan, trafik düzeyi düşük ya da orta olan yapılarda Last-Modified yeterlidir. Ek yapılandırma gerektirmez; her iki başlıcı sunucu yazılımı varsayılan olarak gönderir. İçerik nadiren değişiyor ve saniye düzeyindeki granularite sorunu yaşanmıyorsa bu mekanizma güvenilir biçimde çalışır.

Load balancer arkasında birden fazla sunucu varsa ETag kullanılacaksa inode bileşeni yapılandırılmalı ya da hash tabanlı üretim tercih edilmelidir. Bu yapılandırma ihmal edilirse ETag mekanizması amacının tersine işler: her istek farklı ETag değeriyle karşılaşır, 304 hiç dönmez, tüm kaynaklar yeniden indirilir. Bu durumda ETag tamamen devre dışı bırakmak daha az zararlıdır.

Sık ve hızlı değişen içeriklerin sunulduğu CI/CD ortamlarında, ya da sub-second değişikliklerin önem taşıdığı durumlarda hash tabanlı ETag güçlü ve güvenilir doğrulama sağlar. Her iki header'ı da göndermek — ve tarayıcının ETag'i önceliklendireceğini bilmek — hem eski hem yeni istemcilerle uyumluluğu birlikte sağlar.

Koşullu istek mekanizması basit görünür ama yüksek trafikli ortamlarda bant genişliği tasarrufu ve origin sunucu üzerindeki yük azalması bakımından somut kazanımlar üretir. Her doğrulama isteği sonucunda 304 dönüyorsa tam içerik aktarımından kaçınılıyor demektir; bu hem kullanıcı için hem de altyapı için anlamlı bir performans farkı yaratır.

Last-Modified ve ETag birbirini dışlamaz, birbirini tamamlar. Her ikisini de göndermek tavsiye edilir; hem eski istemcilerle uyumluluk korunur hem de ETag'in sunduğu hassas doğrulamadan yararlanılır. Bu header'lardan birini gereksiz yere çıkarmak doğrulama mekanizmasını zayıflatır.

Gerçek tercih noktası altyapı yapılandırmasındadır. Çok sunuculu ortamlarda ETag tutarsızlığı mekanizmanın tam tersine işlemesine yol açabilir. Bu nedenle ETag'e geçmeden önce sunucuların aynı kaynak için aynı değeri ürettiğini doğrulamak ve CDN katmanının bu değerleri nasıl işlediğini anlamak ilk adımdır. Bunlar netleşmeden yapılan bir tercih, fark yaratan değil sorun yaratan bir yapılandırma değişikliği olabilir.