İçeriğe geç
Süreçlerinize uygun yazılımı birlikte planlayalım. Demo ve teklif için arayın: +90 546 737 48 29

TR EN DE

Nginx'te önbellek ve sıkıştırma

Bir web sayfasının hızını iki soru belirler: aynı içerik kaç kez yeniden üretiliyor ve ağ üzerinden kaç bayt taşınıyor? Önbellek (cache) ilk soruyu yanıtlar: bir kez hazırlanan içeriğin kopyası saklanır ve sonraki isteklerde yeniden üretilmeden sunulur. Sıkıştırma ikinci soruyu yanıtlar: yanıt gönderilmeden önce küçültülür, tarayıcı da onu açar.

Nginx bu iki işi birkaç yönerge (directive) ile yapar. Bu rehber önce her birinin ne işe yaradığını, sonra nasıl ayarlanacağını ve en önemlisi neyin önbelleğe alınmaması gerektiğini anlatır. Örnekler genel amaçlıdır; değerleri kendi sitenize göre seçin ve her değişiklikten sonra yapılandırmayı sınayın.

Kısaca

  • Tarayıcı önbelleği tekrar gelen ziyaretçinin dosyaları yeniden indirmesini önler.
  • gzip, metin tabanlı yanıtları küçültür; görsel ve arşivlere uygulanmaz.
  • proxy_cache, arka uç sunucusunun yanıtını saklayıp sonraki isteklere doğrudan verir.
  • Oturumlu ve kişiye özel sayfalar ortak önbelleğe alınmaz.

Dikkat

Yanlış kurulmuş bir sunucu önbelleği, bir kullanıcıya ait sayfayı başka bir kullanıcıya gösterebilir. Oturum açılan, sepet ya da kişisel bilgi içeren sayfaları önbelleğin dışında tuttuğunuzdan emin olmadan proxy_cache ya da fastcgi_cache açmayın.

Bu sayfada

Üç araç: tarayıcı önbelleği, sıkıştırma, sunucu önbelleği

  1. Hangi önbellek nerede durur?

    "Önbellek" tek bir şey değildir; istek yolunun farklı noktalarında üç ayrı kopya tutulabilir:

    • Tarayıcı önbelleği: Ziyaretçinin kendi cihazındadır. Sunucu, yanıt başlıklarıyla "bu dosyayı şu kadar süre saklayabilirsin" der; tarayıcı o süre boyunca dosyayı yeniden istemez.
    • Sunucu önbelleği (proxy_cache / fastcgi_cache): Nginx'in diskindedir. Nginx, ters vekil (reverse proxy) olarak arka uç sunucusundan (backend) aldığı yanıtı saklar ve aynı adrese gelen sonraki istekleri arka uca hiç gitmeden yanıtlar. Tüm ziyaretçiler için ortaktır.
    • Ara önbellekler: CDN gibi hizmetler de aynı başlıklara bakarak kendi kopyalarını tutar. Ayrıntı için CDN rehberine bakın.

    Sıkıştırma ise bir kopya tutmaz; yanıtı ağda taşınırken küçültür. Üçü birbirinin yerine geçmez, birlikte kullanılır.

    Şema: tarayıcı önbelleği ziyaretçinin cihazında, sıkıştırma ağ üzerinde, sunucu önbelleği Nginx ile arka uç sunucusu arasında çalışır : Büyüt
  2. Statik dosyalar için tarayıcı önbelleği

    CSS, JavaScript, görsel ve yazı tipi dosyaları sık değişmez. expires yönergesi yanıta Expires ve Cache-Control: max-age başlıklarını ekler; add_header Cache-Control ile ek değerler (ör. public, immutable) verilir.

    Süreyi belirleyen şey, dosyanın adresinin değişip değişmediğidir:

    • Sürümlü dosya adları (ör. app.3f9a1c.css): içerik değişince ad da değiştiği için çok uzun süre (ör. bir yıl) ve immutable verilebilir. immutable, tarayıcıya "süre dolana kadar bu dosyayı yeniden doğrulamana gerek yok" der.
    • Adı sabit dosyalar (ör. stil.css): uzun süre verirseniz güncellemeyi ziyaretçi geç görür. Daha kısa bir süre seçin ya da dosya adına sürüm ekleyin.
    • HTML sayfaları: genellikle no-cache verilir; tarayıcı kopyayı saklar ama her kullanımdan önce sunucuya sorar.
    Nginx
    # Sürümlü dosyalar (ör. /assets/app.3f9a1c.css): içerik değişince ad da değişir
    location ^~ /assets/ {
        expires 1y;
        add_header Cache-Control "public, immutable";
        access_log off;
    }
    
    # Diğer statik dosyalar: adı sabit olduğu için daha kısa süre
    location ~* \.(?:css|js|jpg|jpeg|png|gif|webp|svg|ico|woff2)$ {
        expires 30d;
        add_header Cache-Control "public";
    }
    
    # HTML sayfaları: kopya saklanır ama her kullanımdan önce sunucuya sorulur
    location / {
        add_header Cache-Control "no-cache";
        try_files $uri $uri/ =404;
    }

    İki ayrıntıya dikkat edin. İlk blokta ^~ vardır; olmasaydı /assets/app.css isteği alttaki düzenli ifadeli location ile eşleşir ve kısa süre uygulanırdı. İkincisi, add_header yönergeleri üst düzeyden yalnızca bulunulan düzeyde hiç add_header yoksa devralınır; bir location içine tek bir add_header yazdığınızda server düzeyinde tanımlı güvenlik başlıkları o konumda kaybolur ve yeniden yazılmaları gerekir.

  3. gzip ile sıkıştırma

    Tarayıcı isteğinde Accept-Encoding: gzip başlığıyla sıkıştırılmış yanıt kabul ettiğini bildirir; Nginx yanıtı sıkıştırıp Content-Encoding: gzip ile gönderir. HTML, CSS, JavaScript, JSON ve SVG gibi metin tabanlı içerik belirgin biçimde küçülür.

    Nginx
    # http bloğunun içinde: tüm siteler için geçerli olur
    gzip on;
    gzip_comp_level 5;
    gzip_min_length 1024;
    gzip_vary on;
    gzip_proxied any;
    
    # text/html her zaman sıkıştırılır; bu listeye yazılmaz
    gzip_types
        text/plain
        text/css
        text/xml
        application/json
        application/javascript
        application/xml
        application/rss+xml
        image/svg+xml;
    • gzip on; sıkıştırmayı açar. Tek başına yalnızca text/html yanıtlarını sıkıştırır.
    • gzip_types ek içerik türlerini belirtir. text/html her zaman sıkıştırılır; listeye yazılmaz (yazılırsa Nginx yinelenen tür uyarısı verir).
    • gzip_min_length bu bayt sayısından kısa yanıtları sıkıştırmaz (varsayılan 20). Çok küçük yanıtlarda kazanç olmadığı için daha yüksek bir eşik seçilir.
    • gzip_comp_level 1–9 arasıdır (varsayılan 1). Yüksek düzey daha çok işlemci harcar, kazanç ise giderek azalır; orta bir değer çoğu site için yeterlidir.
    • gzip_vary on; yanıta Vary: Accept-Encoding ekler; ara önbelleklerin sıkıştırılmış ve sıkıştırılmamış kopyaları karıştırmasını önler.
    • gzip_proxied: Nginx, başka bir vekil sunucu (proxy) üzerinden gelen istekleri (istekte Via başlığı olanları) varsayılan olarak sıkıştırmaz. Sitenizin önünde CDN ya da başka bir vekil varsa bu yönerge gerekir.

    JPEG, PNG, WebP, video, ZIP ve PDF gibi biçimler zaten sıkıştırılmıştır; bunları listeye eklemek işlemciyi boşa harcar.

    Brotli, gzip'e alternatif bir sıkıştırma yöntemidir. Nginx'in standart paketinde yer almaz; ayrı bir modülün kurulmasını gerektirir. Modül yokken brotli on; yazmak yapılandırma hatasına yol açar. Brotli kullansanız bile gzip'i açık bırakın; onu desteklemeyen istemciler gzip alır.

    Şema: tarayıcı Accept-Encoding: gzip gönderir, Nginx metin tabanlı yanıtı sıkıştırıp Content-Encoding: gzip ile döndürür; görseller ve arşivler sıkıştırılmaz : Büyüt
  4. proxy_cache ile sunucu önbelleği

    Nginx arka uç sunucusunun önünde ters vekil olarak çalışıyorsa (bkz. reverse proxy kurulumu), yanıtları diskte saklayabilir. Aynı adrese gelen ilk istek arka uca gider ve yanıt saklanır (ıska, MISS); sonraki istekler süre dolana kadar doğrudan önbellekten yanıtlanır (isabet, HIT).

    Nginx
    # Önbellek alanı: dizin, anahtar bölgesi (10 MB), disk sınırı, kullanılmayanı silme süresi
    proxy_cache_path /var/cache/nginx/site levels=1:2 keys_zone=site_onbellek:10m
                     max_size=1g inactive=60m use_temp_path=off;
    
    # Oturum çerezi varsa 1, yoksa 0 (çerez adını uygulamanıza göre değiştirin)
    map $cookie_PHPSESSID $onbellek_atla {
        default 1;
        ""      0;
    }
    
    server {
        listen 80;
        server_name ornek.com;
    
        # Herkese aynı görünen sayfalar: önbellekli
        location / {
            proxy_pass http://127.0.0.1:8080;
            proxy_set_header Host $host;
            proxy_set_header X-Real-IP $remote_addr;
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
            proxy_set_header X-Forwarded-Proto $scheme;
    
            proxy_cache site_onbellek;
            proxy_cache_key $scheme$host$request_uri;
            proxy_cache_valid 200 301 10m;
            proxy_cache_valid 404 1m;
    
            # Oturumu olan istek: önbellekten yanıtlama, yanıtı da saklama
            proxy_cache_bypass $onbellek_atla;
            proxy_no_cache $onbellek_atla;
    
            # Arka uç yanıt veremezse süresi dolmuş kopyayı sun
            proxy_cache_use_stale error timeout updating http_500 http_502 http_503 http_504;
            proxy_cache_lock on;
    
            add_header X-Cache-Status $upstream_cache_status;
        }
    
        # Yönetim paneli, sepet ve hesap sayfaları: önbellek yok
        location ~ ^/(yonetim|sepet|hesabim)(/|$) {
            proxy_pass http://127.0.0.1:8080;
            proxy_set_header Host $host;
            proxy_set_header X-Real-IP $remote_addr;
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
            proxy_set_header X-Forwarded-Proto $scheme;
        }
    }
    • proxy_cache_path yalnızca http düzeyinde yazılır: dosyaların duracağı dizin, anahtarların tutulduğu paylaşımlı bellek bölgesi (keys_zone=ad:boyut), disk üst sınırı (max_size) ve bu süre boyunca hiç istenmeyen kayıtların silinmesi (inactive).
    • proxy_cache bölgeyi o location için etkinleştirir.
    • proxy_cache_key iki isteğin "aynı" sayılmasını belirler. İçerik başka bir şeye göre de değişiyorsa (ör. dil çerezi) o değer anahtara eklenmelidir; yoksa bir dilde üretilen sayfa diğer dili isteyene verilir.
    • proxy_cache_valid durum koduna göre saklama süresidir. Arka ucun gönderdiği Cache-Control ya da Expires başlığı varsa o önceliklidir.
    • proxy_cache_bypass isteğin önbellekten yanıtlanmamasını, proxy_no_cache yanıtın önbelleğe yazılmamasını sağlar. Verilen değer boş ya da "0" değilse koşul geçerlidir. Örnekte map, oturum çerezi olan isteklerde değişkeni 1 yapar; çerez adını kendi uygulamanıza göre değiştirin.
    • proxy_cache_use_stale, arka uç hata verdiğinde ya da yanıt vermediğinde süresi dolmuş kopyanın sunulmasına izin verir; kısa kesintilerde site açık kalır.
    • add_header X-Cache-Status $upstream_cache_status; her yanıta önbellek durumunu yazar.

    Nginx varsayılan olarak yalnızca GET ve HEAD isteklerini önbelleğe alır; Set-Cookie içeren ya da Cache-Control başlığında private, no-cache, no-store bulunan yanıtları saklamaz. Bu davranışı proxy_ignore_headers ile kapatmak, kişisel içeriğin sızmasının en sık nedenidir; ne yaptığınızdan emin değilseniz kullanmayın.

    Akış şeması: istek gelir, önbellekte geçerli kopya varsa doğrudan verilir (HIT); yoksa arka uç sunucusuna gidilir, yanıt saklanır ve döndürülür (MISS) : Büyüt
  5. Neyi önbelleğe almamalı?

    Sunucu önbelleği tüm ziyaretçiler için ortaktır. Kural basittir: yanıt, isteği yapan kişiye göre değişiyorsa ortak önbelleğe girmez.

    • Oturum açılmış sayfalar: hesabım, siparişlerim, profil, kişiye özel fiyat ya da içerik.
    • Sepet ve ödeme adımları.
    • Yönetim paneli ve giriş sayfaları.
    • Set-Cookie içeren yanıtlar: önbelleğe alınırsa bir kullanıcının oturum çerezi başkasına gönderilir.
    • Form gönderimleri (POST) ve tek kullanımlık belirteç (ör. CSRF) içeren sayfalar.
    • API yanıtları: yetkilendirme başlığına göre değişenler.

    En güvenli düzen, önbelleği yalnızca açıkça seçtiğiniz adreslerde (ana sayfa, ürün ve yazı sayfaları gibi herkese aynı görünen içerik) etkinleştirmek, panel ve hesap adreslerini ayrı bir location ile önbelleksiz bırakmaktır. Oturum konusundaki genel önlemler için giriş ve oturum güvenliği rehberine bakın.

    Karşılaştırma: herkese aynı görünen sayfalar ve statik dosyalar önbelleğe alınır; oturumlu sayfalar, sepet, yönetim paneli ve Set-Cookie içeren yanıtlar alınmaz : Büyüt

Çalıştığını doğrulama: X-Cache-Status

Yapılandırmayı sınayıp yeniden yükledikten sonra yanıt başlıklarına bakın. Aynı adresi iki kez isteyin: ilk yanıtta MISS, ikincide HIT görmelisiniz.

Bash
# Yapılandırmayı sına, sorun yoksa yeniden yükle
sudo nginx -t && sudo systemctl reload nginx

# Statik dosya başlıkları: Cache-Control ve Expires görünmeli
curl -s -o /dev/null -D - https://ornek.com/assets/app.3f9a1c.css | grep -i -E "cache-control|expires"

# Sıkıştırma: Content-Encoding: gzip ve Vary: Accept-Encoding görünmeli
curl -s -o /dev/null -D - -H "Accept-Encoding: gzip" https://ornek.com/ | grep -i -E "content-encoding|vary"

# Sunucu önbelleği: aynı adresi iki kez isteyin (ilki MISS, ikincisi HIT)
curl -s -o /dev/null -D - https://ornek.com/ | grep -i x-cache-status
curl -s -o /dev/null -D - https://ornek.com/ | grep -i x-cache-status
DeğerAnlamı
MISSÖnbellekte kopya yoktu; yanıt arka uçtan alındı (ve uygunsa saklandı).
HITYanıt doğrudan önbellekten verildi; arka uca gidilmedi.
BYPASSproxy_cache_bypass koşulu sağlandı; önbellek atlandı.
EXPIREDKopyanın süresi dolmuştu; yanıt arka uçtan yeniden alındı.
STALEArka uç yanıt veremedi; süresi dolmuş kopya sunuldu.
UPDATINGKopya yenilenirken eski kopya sunuldu.
REVALIDATEDArka uç, süresi dolmuş kopyanın hâlâ geçerli olduğunu doğruladı.

Sürekli MISS görüyorsanız arka ucun yanıtına bakın: Set-Cookie ya da Cache-Control: no-store gönderiyor olabilir. Örneğin PHP'de oturum başlatmak, varsayılan ayarlarla yanıta önbelleği engelleyen başlıklar ekler. Başlığı canlı sitede herkese göstermek istemiyorsanız sınama bittikten sonra kaldırabilirsiniz.

PHP-FPM kullanıyorsanız: fastcgi_cache

Nginx PHP'yi başka bir web sunucusuna değil doğrudan PHP-FPM'e iletiyorsa (fastcgi_pass), aynı mantık fastcgi_cache ailesiyle kurulur: fastcgi_cache_path, fastcgi_cache, fastcgi_cache_valid, fastcgi_cache_bypass, fastcgi_no_cache. Önemli bir fark, fastcgi_cache_key için varsayılan değer olmamasıdır; açıkça yazılmalıdır.

Nginx
fastcgi_cache_path /var/cache/nginx/php levels=1:2 keys_zone=php_onbellek:10m
                   max_size=512m inactive=60m;

map $cookie_PHPSESSID $onbellek_atla {
    default 1;
    ""      0;
}

server {
    listen 80;
    server_name ornek.com;
    root /var/www/ornek.com/public;
    index index.php;

    location / {
        try_files $uri $uri/ /index.php?$query_string;
    }

    location ~ \.php$ {
        try_files $uri =404;
        include fastcgi_params;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
        fastcgi_pass unix:/run/php/php-fpm.sock;   # soket yolu dağıtıma göre değişir

        fastcgi_cache php_onbellek;
        fastcgi_cache_key $scheme$request_method$host$request_uri;   # varsayılanı yoktur
        fastcgi_cache_valid 200 5m;
        fastcgi_cache_bypass $onbellek_atla;
        fastcgi_no_cache $onbellek_atla;

        add_header X-Cache-Status $upstream_cache_status;
    }
}

PHP-FPM bağlantısının kendisi için Nginx ve PHP-FPM rehberine bakın.

Önbelleği temizleme

İçerik değişti ama önbellek eski kopyayı sunuyorsa birkaç yol vardır:

  • Süreyi kısa tutmak: Sık değişen sayfalar için birkaç dakikalık proxy_cache_valid çoğu zaman yeterlidir; temizlemeye gerek kalmaz.
  • Dosyaları silmek: Önbellek dizinindeki dosyaları silmek tüm önbelleği boşaltır; Nginx sonraki isteklerde yanıtı arka uçtan yeniden alır. Yalnızca proxy_cache_path ile tanımladığınız dizini hedefleyin.
  • Anahtarı değiştirmek: proxy_cache_key içine bir sürüm değeri ekleyip değiştirmek, eski kayıtların tümünü bir anda geçersiz kılar; eski dosyalar inactive süresi sonunda kendiliğinden silinir.
  • Tek adresi yenilemek: proxy_cache_bypass koşulunu yalnızca sizin gönderebileceğiniz bir işarete (ör. yalnızca kendi IP adresinizden kabul edilen bir istek başlığı) bağlarsanız, o istek arka uçtan taze yanıt alır ve kayıt yenilenir.
Bash
# Tüm sunucu önbelleğini boşalt.
# Yol, proxy_cache_path (ya da fastcgi_cache_path) ile tanımladığınız dizin olmalı; başka dizin yazmayın.
sudo find /var/cache/nginx/site -type f -delete

Tek tek adresleri silen hazır bir "purge" özelliği, bildiğimiz kadarıyla Nginx'in açık kaynak sürümünde yerleşik değildir; ticari sürümde ya da üçüncü taraf modüllerle sağlanır. Kurulumunuzda hangisinin bulunduğunu kendi paketinizin belgelerinden doğrulayın.

Tarayıcı önbelleğini ise sunucudan temizleyemezsiniz; ziyaretçinin cihazındadır. Bu yüzden uzun süreli statik dosyalarda sürümlü dosya adı kullanmak tek güvenilir yoldur.

Sık yapılan hatalar

  • Adı değişmeyen CSS ve JavaScript dosyalarına bir yıllık süre vermek; güncelleme ziyaretçilere ulaşmaz.
  • gzip_types listesine text/html ya da görsel türleri eklemek.
  • Oturum çerezini denetlemeden tüm siteye proxy_cache açmak.
  • proxy_ignore_headers Set-Cookie Cache-Control; satırını ne yaptığını bilmeden kopyalamak.
  • Dile, cihaza ya da para birimine göre değişen içerikte bu değeri önbellek anahtarına eklememek.
  • Bir location içine add_header yazıp üst düzeydeki güvenlik başlıklarının kaybolduğunu fark etmemek (bkz. güvenlik başlıkları).
  • Önbellek dizinini Nginx'in çalıştığı kullanıcının yazamayacağı bir yere koymak.

Kontrol listesi

  • Statik dosyalar expires ile süre alıyor; uzun süre yalnızca sürümlü dosya adlarında.
  • gzip açık; gzip_types yalnızca metin tabanlı türleri içeriyor, gzip_vary on.
  • Sunucu önbelleği yalnızca herkese aynı görünen adreslerde etkin.
  • Oturum çerezi olan istekler proxy_cache_bypass ve proxy_no_cache ile hariç.
  • Yönetim paneli, sepet ve hesap sayfaları önbelleksiz.
  • X-Cache-Status ile MISS ve HIT gözlendi; oturum açıkken BYPASS görülüyor.
  • Önbelleği nasıl temizleyeceğiniz yazılı ve denenmiş.
  • Her değişiklikten sonra nginx -t çalıştırıldı.

Sık sorulan sorular

Önbellek açınca sitedeki değişiklikler neden hemen görünmüyor?

Çünkü tarayıcı ya da sunucu, süresi dolmamış eski kopyayı sunuyor. Sunucu önbelleğini temizleyebilir ya da süresini kısaltabilirsiniz; tarayıcı önbelleği için kalıcı çözüm, statik dosyalarda sürümlü dosya adı kullanmaktır.

gzip mi, Brotli mi kullanmalıyım?

gzip Nginx ile birlikte gelir ve her tarayıcıda çalışır; önce onu açın. Brotli ayrı bir modül gerektirir. Modülü kurabiliyorsanız ikisini birlikte kullanabilirsiniz; tarayıcı desteklediğini seçer.

Sürekli MISS görüyorum, neden?

En sık nedenler: arka ucun Set-Cookie ya da Cache-Control: no-store, private göndermesi, isteğin oturum çerezi taşıması, proxy_cache_valid tanımlanmamış olması ya da adresin her istekte değişen bir sorgu parametresi içermesi.

proxy_cache ile fastcgi_cache arasındaki fark nedir?

Mantık aynıdır; fark Nginx'in yanıtı nereden aldığıdır. Arka uç HTTP ile konuşan bir sunucuysa (proxy_pass) proxy_cache, doğrudan PHP-FPM ise (fastcgi_pass) fastcgi_cache kullanılır.

CDN kullanıyorsam Nginx önbelleğine gerek var mı?

İkisi birbirini tamamlar. CDN içeriği ziyaretçiye yakın noktalardan sunar; Nginx önbelleği ise CDN'in sunucunuza ilettiği isteklerde uygulamanın yükünü azaltır. Önbellek başlıklarınız doğruysa ikisi de aynı kurallara uyar.

BYK Yazılım Destek Ekibi
Bu rehber BYK Yazılım destek ekibi tarafından hazırlanır ve düzenli olarak gözden geçirilir. Son güncelleme: 04.10.2026.

İlgili rehberler

Web sitenizin altyapısını birlikte konuşalım

BYK Yazılım kurumsal web siteleri geliştirir. Sitenizle ilgili sorularınız için bize yazabilirsiniz.

Bize ulaşın Kurumsal web sitesi hizmetimiz