Bir WordPress sitesi, bir Laravel API projesi veya modern bir React SPA uygulaması geliştirirken performans konuşulan her toplantıda şu soru mutlaka gelir: Tarayıcı ve CDN önbelleğini doğru ayarlasak bu site ne kadar hızlanır ve altyapı maliyeti ne kadar düşer? HTTP Cache-Control başlıkları, ETag ve CDN tarafındaki önbellek kuralları doğru kurgulandığında, hem Core Web Vitals skorlarınız iyileşir hem de sunucularınız gereksiz yükten kurtulur. DCHost ekibi olarak sahada en çok gördüğümüz problemlerden biri, bu başlıkların ya gereğinden agresif ya da tamamen kapalı kullanılması. Sonuç; ya eski içerik gösteren sayfalar ya da her istekte sunucuyu yoran dinamik cevaplar oluyor.
Bu yazıda HTTP Cache-Control, ETag ve CDN önbellek kurallarını; WordPress, Laravel ve SPA (React, Vue, Angular) projeleri özelinde, gerçekçi senaryolarla ele alacağız. Hangi dosyayı ne kadar süre cachelemek mantıklı, HTML sayfalarda ne kadar agresif olunabilir, API cevaplarında ETag ne işimize yarar, CDN kuralı ile origin sunucu ayarları nasıl uyumlu olmalı tek tek üzerinden geçeceğiz. Anlatım boyunca DCHost altyapısında uyguladığımız pratiklerden, sık gördüğümüz hatalardan ve bunları nasıl düzelttiğimizden bahsedeceğim.
Önbellekleme, site hızının ve altyapı maliyetinin en büyük kaldıraçlarından biri. Özellikle medya ve statik dosya ağırlıklı projelerde, doğru HTTP başlıkları ile hem son kullanıcının yaşadığı gecikmeyi hem de sunucu CPU ve disk IO tüketimini dramatik biçimde azaltmak mümkün. Bu etkiyi en net şekilde Core Web Vitals metriklerinde görürsünüz. Tarayıcı, CSS ve JS dosyalarını her sayfa yüklemesinde yeniden indirmek zorunda kalmadığında LCP ve FID değerleri belirgin biçimde iyileşir. Bu konuyu daha derinlemesine okumak isterseniz, Core Web Vitals ve hosting altyapısının etkileşimi başlıklı rehberimize göz atabilirsiniz.
Diğer tarafta CDN kullanıyorsanız, edge sunuculardaki cache hit oranı doğrudan faturanıza ve origin sunucularınızın stabilitesine yansır. Kötü kurgulanmış Cache-Control başlıkları, CDN katmanının HTML ve API cevaplarını yanlış şekilde cachelemesine, kullanıcı başına kişiselleştirilmiş içeriklerin karışmasına ve login sayfalarının statikmiş gibi saklanmasına neden olabilir. Bu yüzden, tarayıcı önbelleğini düşünürken her zaman CDN ile beraber, uçtan uca bir strateji kurmak gerekiyor. DCHost tarafında, yüksek trafikli WordPress ve Laravel projelerinde mimari tasarım yaparken ilk baktığımız maddelerden biri, HTTP önbellek başlıklarının haritasıdır.
HTTP Cache-Control Direktiflerini Doğru Okumak
Cache-Control başlığı, tarayıcının ve ara önbelleklerin (CDN, reverse proxy vb.) içeriği nasıl saklayacağını belirleyen anahtar mekanizma. Temel ve gelişmiş direktifleri netleştirelim.
Temel Cache-Control direktifleri
- max-age=sek: İçeriğin kaç saniye boyunca taze kabul edileceğini belirtir. Örneğin 86400 bir gün demektir.
- s-maxage=sek: Paylaşımlı cacheler (CDN, proxy) için max-age değerini override eder. Tarayıcı farklı, CDN farklı süre kullanabilir.
- public: Cevabın, paylaşımlı cacheler tarafından saklanabileceğini söyler. HTML sayfaları için dikkatli kullanılmalıdır.
- private: Cevabın sadece tarayıcı tarafında cachelenmesi gerektiğini, paylaşımlı cacheler için uygun olmadığını belirtir. Kullanıcıya özel dashboard ve hesap sayfaları için idealdir.
- no-store: İçerik hiç bir şekilde cachelenmesin, disk veya hafızaya yazılmasın demektir. Ödeme sayfaları ve yüksek hassasiyetli veriler için kullanmalısınız.
- no-cache: İsim kafa karıştırıcı; aslında cachelemeyi tamamen kapatmak değildir. İçeriğin cachelenebileceğini ancak her kullanımda origin ile yeniden doğrulanması gerektiğini söyler (ETag veya Last-Modified ile).
Pratikte statik dosyalar için public, max-age yüksek; dinamik HTML ve API cevapları için ise private veya no-store + kısa süreli max-age kombinasyonları kullanılır. Örneğin WordPress ana sayfanız için 60 saniyelik bir mikro cache makul olabilirken, logo PNG için 30 gün cache süresi son derece güvenlidir.
Gelişmiş direktifler: stale-while-revalidate ve stale-if-error
Modern tarayıcılar ve CDNler, iki önemli direktifi daha destekliyor:
- stale-while-revalidate=sek: İçerik aslında süresi dolmuş olsa bile, belirtilen süre boyunca eski versiyonun kullanıcıya gösterilmesine izin verirken arka planda taze versiyonu çekip cachei günceller.
- stale-if-error=sek: Origin erişilemez veya hata veriyorsa, belirtilen süre boyunca eski cache içeriğinin kullanılmasına izin verir. Kesintilerde hayat kurtarıcıdır.
Bu mekanizmalar, özellikle CDN seviyesinde kullanıldığında kesintisiz yayına ciddi katkı sağlar. Bu konuyu daha önce stale-while-revalidate ve stale-if-error direktiflerinin pratik kullanımı başlıklı yazımızda detaylı anlatmıştık. Buradaki fikir şu: Origininiz kısa süreli bir problem yaşasa bile, kullanıcı tarafında çoğu zaman kimse fark etmez.
ETag ve Last-Modified ile Koşullu İstekler
Cache-Control ile ne kadar süre cacheleneceğini belirledik. Peki içerik değiştiğinde tarayıcı bunu nasıl anlayacak? Tam burada ETag ve Last-Modified devreye giriyor.
ETag nedir, nasıl çalışır
ETag, sunucunun her cevap için ürettiği benzersiz bir içerik etiketi. Genelde dosyanın hash değeri, inode bilgisi veya benzeri bir özet üzerinden oluşturulur. İstemci, ilk istekte ETag değerini response header olarak alır ve sonraki isteğinde If-None-Match başlığı ile geri gönderir. Eğer sunucudaki içerik değişmediyse 304 Not Modified cevabı döner ve veri tekrar indirilmez; sadece headerlar güncellenir.
Bu mekanizma özellikle şu durumlarda çok değerlidir:
- max-age süresi nispeten kısa tutulmak zorundaysa bile gereksiz veri transferini azaltmak
- API cevapları için, veri değişmediği sürece network ve CPU maliyetini kısmak
- Dinamik HTML sayfalarda, değişiklik olmayan kullanıcılar için daha hızlı yanıt sağlamak
Last-Modified ile birlikte kullanım ve CDN etkisi
Last-Modified başlığı, içeriğin son değiştirilme zamanını belirtir. Tarayıcı bir sonraki istekte If-Modified-Since ile gelir ve içerik değişmemişse yine 304 döndürülür. ETag ve Last-Modified genelde birlikte kullanılır; bazı durumlarda sadece Last-Modified yeterli olabilir.
CDN tarafında ise dikkat edilmesi gereken nokta şudur: Bazı CDNler, ETag başlıklarını manipüle edebilir veya origin ile edge arasında farklılaştırabilir. Ayrıca ETag değeriniz sunucudaki dosyanın inode bilgisinden türetiliyorsa, çoklu sunucu mimarilerinde (örneğin DCHost üzerinde birden fazla web sunucusuna dağıtılmış WordPress clusterı) aynı içeriğe farklı ETagler üretilebilir. Bu da cache isabet oranını düşürür. Bu yüzden, mümkün olduğunca içerik tabanlı hash veya build sürecinde üretilen sabit ETag mekanizmalarını tercih etmek daha sağlıklı olur.
WordPress İçin Doğru Tarayıcı Önbellekleme Stratejisi
WordPress ekosisteminde en sık gördüğümüz senaryo şu: Statik dosyalar agresif şekilde cachelenmemiş, HTML sayfalar ise ya tamamen dinamik ya da CDN düzeyinde yanlışlıkla public cachelenmiş. Doğru ayrımı yapmak için WordPressi ikiye bölmek gerekir: Statik varlıklar ve HTML çıktılar.
Statik dosyalar: CSS, JS, görseller ve yazı tipleri
WordPress tema ve eklentileriniz çoğunlukla versiyon parametreleri ile cache busting uygular. Örneğin style.css dosyanız şu şekilde çağrılır:
/wp-content/themes/tema/style.css?ver=1.4.3Bu sayede dosyaya 1 yıl bile cache süresi verseniz, dosya değiştiğinde versiyon numarası değişeceği için tarayıcı yeni dosyayı indirir. Bu, uzun süreli cache ve güvenli güncelleme kombinasyonunun altın standardıdır.
Önerilen ayarlar kabaca şöyle olabilir:
- CSS, JS, font ve görseller için: Cache-Control public, max-age=2592000 (30 gün) veya daha uzun
- immutable direktifini ekleyerek, aynı dosya ismi değişmediği sürece tarayıcının yeniden doğrulama ihtiyacını azaltabilirsiniz
location ~* .(css|js|png|jpe?g|gif|svg|webp|ico|woff2?)$ {n expires 30d;n add_header Cache-Control 'public, max-age=2592000, immutable';n}Görsel optimizasyonu ve CDN tarafındaki ayarlarla birlikte düşünmek isterseniz, WebP, AVIF ve CDN alt alan adları ile görsel SEO stratejileri yazısındaki önerilerle bu ayarları birleştirebilirsiniz.
HTML sayfalar, WooCommerce sayfaları ve kullanıcıya özel içerik
HTML tarafında ise biraz daha dikkatli olmak şart. Ana sayfa, kategori sayfaları ve blog yazıları için tam sayfa önbellekleme (server side cache) kullanıyorsanız, tarayıcıya uzun süreli cache süresi vermenize çoğu zaman gerek kalmaz. Burada amaç tarayıcıdan çok, sunucuyu rahatlatan reverse proxy veya uygulama içi cachelerdir. Yine de mikro önbellekleme ile 30 ila 120 saniye arasında bir max-age, özellikle yoğun trafikli haber ve blog sitelerinde oldukça işe yarar.
WooCommerce tarafında ise sepet, ödeme ve hesap sayfaları kesinlikle public cachelenmemelidir. Bu sayfalar için:
- Cache-Control no-store, no-cache, must-revalidate
- Pragma no-cache (eski tarayıcılar için)
- Vary Cookie veya Authorization gibi başlıklarla CDN seviyesinde de cachelenmesi engellenmelidir
CDN ve edge kuralları ile HTML cachei yönetmek üzerine daha odaklı bir rehbere ihtiyacınız varsa, WordPress için CDN önbellek kuralları ve WooCommercede HTML cache bypass stratejileri yazımızı da bu makale ile birlikte okumanızı öneririm.
Nginx ve Apache için örnek WordPress ayarları
Nginx üzerinde tipik bir WordPress kurulumunda, aşağıdaki gibi bir ayrım yapılabilir:
# Statik dosyalar uzun süre cachenlocation ~* .(css|js|png|jpe?g|gif|svg|webp|ico|woff2?)$ {n expires 30d;n add_header Cache-Control 'public, max-age=2592000, immutable';n}nn# Dinamik PHP sayfalar için kısa süreli veya hiç cache yoknlocation ~ .php$ {n add_header Cache-Control 'private, no-cache, no-store, must-revalidate';n include fastcgi_params;n fastcgi_pass php-fpm:9000;n}Tabii ki burada php-fpm havuz ayarları ve OPcache yapılandırmasının da devreye girdiğini unutmayalım. Sunucu tarafı WordPress optimizasyonu için, PHP-FPM, OPcache ve Redis ile WordPress optimizasyon rehberimizi inceleyebilirsiniz. DCHost altyapısında sıkça kullandığımız yapı, tam sayfa cache + uzun süreli statik asset cache kombinasyonudur.
Laravel Uygulamalarında Cache-Control ve ETag
Laravel tarafında hem klasik web uygulamaları hem de sadece API sağlayan servisler sıkça karşımıza çıkıyor. Çoğu projede önbellekleme sadece uygulama içi cache mekanizmaları ile sınırlı kalıyor; HTTP seviyesinde ise neredeyse hiç ayar yapılmıyor. Oysa Laravel, bu konuda gayet esnek bir temel sunuyor.
Asset versiyonlama: mix ve vite kullanımı
Önce, statik dosyalardan başlayalım. Laravel Mix veya Vite kullandığınızda, derlenen CSS ve JS dosyaları genelde şu formatta üretilir:
/build/assets/app.7c3f9a2d.jsn/build/assets/app.19b5c811.cssBu hashli dosya isimleri, agresif tarayıcı ve CDN cachei için biçilmiş kaftandır. Çünkü dosya içeriği değiştiğinde isim de değişir; eski isimli dosyalar cachete kalsa bile yeni versiyon otomatik olarak çağrılır.
Bu durumda, Nginx veya Apache seviyesinde şu mantıkla hareket edebilirsiniz:
- build, public, storage gibi asset dizinleri için public, max-age=31536000, immutable
- Sık değişmeyen fakat hashlenmemiş dosyalar için max-age daha kısa
Bu yapı, özellikle DCHost üzerinde yüksek trafikli Laravel projelerinde CPU yükünü ciddi ölçüde azaltıyor; çünkü her sayfa yüklemesinde tekrar tekrar indirilen ağır JS bundleları devreden çıkmış oluyor.
API cevapları için Cache-Control ve ETag stratejisi
Laravel ile yazılmış APIlerde, GET istekleri için ETag ve kısa süreli max-age kombinasyonu çok işe yarar. Örneğin ürün listesini veya sabit referans verileri dönen uç noktalar için şu stratejiyi izleyebilirsiniz:
- Cache-Control public, max-age=60, stale-while-revalidate=30
- ETag başlığı ile içerik değişmediğinde 304 Not Modified döndürmek
- Yetkilendirme gerektiren uç noktalar için ise private ve genelde no-store kullanmak
Laravelde bir response için ETag eklemek oldukça basit:
return response($content)n ->header('Cache-Control', 'public, max-age=60, stale-while-revalidate=30')n ->setEtag(sha1($content));Tabii gerçek dünyada ETagi sadece içerikten değil, versiyon numaranızdan, güncelleme zamanından veya veritabanı satırlarının checksumlarından da türetebilirsiniz. Önemli olan, içerik değiştiğinde ETagin de değişmesini sağlamak.
Laravel prod ortam optimizasyonu ile HTTP cachei birlikte düşünmek isterseniz, Laravel prod ortam optimizasyon rehberi bu yazının iyi bir tamamlayıcısı olacaktır.
SPA Projeleri (React, Vue, Angular) İçin Önbellek Kuralları
SPA dünyasında önbellekleme stratejisi WordPress veya klasik Laravel uygulamalarından biraz farklı. Çünkü çoğu zaman tek bir index.html dosyası ve onun referans verdiği büyük JS ve CSS bundleları üzerinden çalışıyorsunuz. Ayrıca API istekleri genelde ayrı bir origin veya alt yol üzerinden servis ediliyor.
index.html için kısa süreli fakat kontrollü cache
SPA projelerinde index.html, uygulamanızın giriş noktası ve çoğu zaman çok küçük bir dosya. Bu dosyanın agresif şekilde cachelenmesi, yeni deploylardan sonra kullanıcılara eski versiyonun kalmasını sağlar. Bu yüzden genelde şu yaklaşım tercih edilir:
- Cache-Control no-cache veya max-age=60 gibi kısa bir süre
- ETag veya Last-Modified ile koşullu istek desteği
- CDN tarafında HTML cachei devre dışı bırakmak veya çok kısa tutmak
Böylece kullanıcı sayfanıza her giriş yaptığında en fazla birkaç saniyelik bir gecikmeyle yeni index.html versiyonunu alır ve yeni JS bundlelarına yönlendirilir.
Hashli JS ve CSS dosyaları için agresif cache
Build sürecinde üretilen app.7c3f9a2d.js veya vendor.19b5c811.css gibi hashli dosyalar için tam tersine, mümkün olan en agresif cache politikasını uygulamalısınız:
- Cache-Control public, max-age=31536000, immutable
- CDN seviyesinde de aynı veya daha uzun süre
- Versiyon değişikliğini sadece dosya ismine bırakarak cache busting sağlamak
Bu sayede, kullanıcı siteyi tekrar ziyaret ettiğinde büyük JS bundlelarını neredeyse hiç indirmez; sadece index.html ve gerekirse yeni manifest dosyası güncellenir. Bu yaklaşım TTFByi değil ama FCP ve LCPyi ciddi şekilde iyileştirir.
Service Worker, offline cache ve CDN uyumu
Eğer PWA özellikleri kullanıyor ve service worker ile offline cache yapıyorsanız, HTTP seviyesindeki Cache-Control kurallarınızla çakışmayacak bir mimari kurmanız gerekir. Genel öneri şu şekildedir:
- Service worker scripti ve manifest dosyası için kısa süreli cache ve ETag
- Service workerın network-first, cache-first veya stale-while-revalidate stratejilerini bilinçli seçmek
- CDN tarafında HTML ve service worker için cache bypass kuralları tanımlamak
SPA projelerini aynı alan adında API ile birlikte yayınlama konusu da cache davranışını etkiler. Bu senaryoyu daha detaylı anlattığımız React, Vue ve Angular SPAleri aynı alan adında API ile host etme rehberinde Nginx yönlendirme ve SSL mimarisine ek olarak, cache key ve path bazlı kurallara da değinmiştik.
CDN ile Origin Önbelleğini Uyumlu Hale Getirmek
Tarayıcı ve CDN önbelleği çoğu zaman aynı Cache-Control başlıklarına baksa da, davranışları ve öncelikleri farklıdır. Origin sunucunuzda güzel ayarlar yapıp CDN düzeyinde bunları yanlış override ederseniz, çok kafa karıştırıcı sonuçlarla karşılaşabilirsiniz.
CDNlerin hangi isteği hangi cache girdisi ile eşleştireceğini belirleyen şey cache keydir. Tipik olarak şu parçaları içerir:
- Host (alan adı)
- Path (istek yolu)
- Sorgu parametreleri (query string) – hepsi veya seçili olanlar
- Bazı headerlar (Accept-Encoding, Authorization vb.)
WordPress ve WooCommerce sitelerinde en kritik nokta, kullanıcıyı tanımlayan cookie değerlerinin cache keye nasıl dahil edileceğidir. Genellikle login olmuş kullanıcıları ve sepet içeren oturumları cache dışında bırakmak için, belirli cookie adlarına göre bypass kuralları yazılır. Örneğin:
- wp_logged_in_ ile başlayan cookie varsa HTML cache bypass
- woocommerce_cart_hash veya woocommerce_items_in_cart varsa cache bypass
Benzer şekilde, Laravel tabanlı bir SaaS uygulamasında Authorization headerı içeren isteklerin CDN seviyesinde cachelenmemesini istersiniz. Bunu Vary Authorization başlığı ve CDN tarafında ek kurallarla destekleyebilirsiniz.
Origin ve CDN arasında rol dağılımı
DCHost ortamında tipik olarak şu rol dağılımını öneriyoruz:
- Origin (Nginx, Apache veya uygulama): Doğru Cache-Control, ETag, Last-Modified ve Vary başlıklarını üretir. Statik dosyalar için uzun süreli, HTML ve API için daha kontrollü süreler belirler.
- CDN: Bu başlıkları varsayılan olarak takip eder, ancak kritik pathler için istisnai edge kuralları tanımlar. Örneğin wp-admin altındaki tüm yolları kesinlikle cachelememek, login ve checkout sayfalarını HTML cache dışında bırakmak gibi.
CDN seçimi ve maliyet optimizasyonu tarafında daha derin bir bakışa ihtiyacınız varsa, CDN trafik maliyetlerini kontrol altına alma rehberinde origin pull, cache hit oranı ve bölgesel fiyatlandırma konularını detaylı ele almıştık. Oradaki önerileri, bu yazıdaki HTTP önbellek stratejisi ile birleştirdiğinizde hem performans hem de fatura tarafında dengeli bir yapı kurabilirsiniz.
Tipik DCHost Senaryoları: WordPress, Laravel API ve SPA
Sahada en sık gördüğümüz üç senaryoyu, somut önbellek kuralları ile özetleyelim.
1. Klasik blog veya kurumsal WordPress sitesi
- Statik varlıklar (wp-content, wp-includes altındaki css, js, img, fonts): public, max-age=2592000 veya 31536000, immutable
- HTML sayfalar (ana sayfa, yazı, kategori): sunucu tarafında tam sayfa cache 60–300 saniye, tarayıcı tarafında kısa max-age (60–120 saniye) veya no-cache
- Yönetim paneli, wp-admin ve wp-login.php: no-store, no-cache, Pragma no-cache ve CDN seviyesinde cache bypass
2. Laravel tabanlı API + admin panel
- Statik assetler (build klasörü): public, max-age=31536000, immutable
- Genel GET uç noktaları (ürün listeleri, sabit içerikler): public, max-age=60–300, ETag ile 304 desteği
- Auth gerektiren GET uç noktaları: private, no-store, kısa max-age veya tamamen kapalı cache
- Admin panel HTML ve JS: private, no-store; CDNde host ediliyorsa path bazlı cache bypass
3. SPA frontend + ayrı API sunucusu
- index.html: no-cache veya max-age=60, ETag desteği
- Hashli JS, CSS, font ve imajlar: public, max-age=31536000, immutable
- API GET uç noktaları: durumuna göre kısa süreli public cache veya private + ETag
- Login ve kullanıcıya özel veri dönen uç noktalar: no-store, Vary Authorization ve CDN cache bypass
Bu senaryoların tamamında ortak nokta şu: Önbellekleme stratejisi sadece bir header eklemekten ibaret değil. Uygulama katmanı, web sunucusu, CDN ve tarayıcı birlikte düşünülüyor. DCHost ekibi olarak yeni bir proje göçü veya kapasite planlaması yaparken, bu dörtlüyü her zaman beraber masaya yatırıyoruz.
Sonuç: HTTP Önbelleği Doğru Kurulduğunda Ne Kazanırsınız
HTTP Cache-Control başlıkları, ETag ve CDN önbellek kuralları doğru kurgulandığında ortaya üç somut kazanım çıkar: Son kullanıcı için belirgin hız artışı, sunucu kaynak kullanımında ciddi azalma ve altyapı maliyetinde gözle görülür düşüş. WordPress tarafında statik varlıkları uzun süreli cacheleyip HTML için akıllı bir tam sayfa cache kurduğunuzda, aynı donanım üzerinde çok daha fazla trafiği rahatlıkla kaldırabilirsiniz. Laravel ve SPA projelerinde ise hashli assetler için agresif cache, index.html ve API cevapları için dengeli bir stratejiyle birleştiğinde, hem yeni deploylarda hem de pik trafikte sistemi ayakta tutmak çok daha kolay hale gelir.
Buradan sonra atabileceğiniz en mantıklı adım, mevcut sitenizin HTTP başlıklarını ve CDN kurallarını gözden geçirmek. Tarayıcı tarafında hangi dosya ne kadar süre cacheleniyor, CDN katmanında hangi pathler HTML cacheleniyor, login veya ödeme sayfaları güvenli mi; hepsini tek tek kontrol edin. İsterseniz, DCHost üzerindeki WordPress, Laravel veya SPA projelerinizi incelerken sizin için özelleştirilmiş bir önbellek stratejisi de çıkarabiliriz. Altyapı tarafında NVMe diskli VPS, dedicated sunucu veya colocation seçenekleriyle, doğru HTTP önbellekleme ayarlarını destekleyen güçlü bir temel kurmak mümkün. Kısacası; önce HTTP başlıklarını temizleyin, ardından ihtiyacınıza uygun DCHost altyapısı ile bu stratejiyi güvenle büyütün.





