Caching

Caching #

Caching adalah salah satu cara paling efektif untuk meningkatkan performa — daripada memproses request yang sama berulang kali, simpan hasilnya dan sajikan langsung. Nginx mendukung dua jenis caching yang saling melengkapi: cache header untuk aset statis di sisi browser, dan proxy cache untuk menyimpan response backend di disk Nginx.

Cache Header untuk Aset Statis #

Cara paling sederhana dan paling efektif: beritahu browser untuk menyimpan aset statis di cache lokal mereka, sehingga request berikutnya tidak perlu ke server sama sekali.

server {
    root /var/www/html;

    # Aset statis yang jarang berubah — cache satu tahun
    location ~* \.(css|js|woff2|woff|ttf|otf|eot)$ {
        expires 1y;
        add_header Cache-Control "public, immutable";
        access_log off;
    }

    # Gambar — cache satu bulan
    location ~* \.(jpg|jpeg|png|gif|webp|svg|ico)$ {
        expires 30d;
        add_header Cache-Control "public";
        access_log off;
    }

    # HTML — jangan cache atau cache sangat singkat
    location ~* \.html$ {
        expires -1;   # no-cache
        add_header Cache-Control "no-store, no-cache, must-revalidate";
    }
}

Directive expires mengatur dua hal sekaligus: header Expires dan header Cache-Control: max-age. Nilai 1y berarti browser menyimpan file selama satu tahun.

Header immutable memberitahu browser bahwa file ini tidak akan pernah berubah selama masa cache-nya — browser tidak perlu melakukan revalidasi sama sekali. Ini hanya tepat untuk file dengan nama yang menyertakan hash konten (misalnya app.a3f8b2c.js dari build tools modern).


Proxy Cache: Cache Response Backend #

proxy_cache menyimpan response dari backend di disk Nginx. Request berikutnya untuk URL yang sama dilayani langsung dari cache tanpa menyentuh backend.

Konfigurasi Cache Zone #

http {
    # Definisikan zona cache di shared memory dan direktori penyimpanan
    # path: direktori penyimpanan cache di disk
    # levels=1:2: struktur subdirektori (untuk performa filesystem)
    # keys_zone=nama:ukuran: nama zone dan ukuran index di memori
    # max_size: ukuran maksimum cache di disk
    # inactive: hapus cache yang tidak diakses dalam waktu ini
    # use_temp_path=off: tulis langsung ke direktori cache (lebih efisien)
    proxy_cache_path /var/cache/nginx
        levels=1:2
        keys_zone=app_cache:10m
        max_size=1g
        inactive=60m
        use_temp_path=off;
}

Menggunakan Cache di Location #

server {
    location /api/ {
        proxy_cache app_cache;

        # Cache key: kombinasi method, host, dan URI
        proxy_cache_key "$request_method$host$request_uri";

        # Cache response ini selama berapa lama berdasarkan status code
        proxy_cache_valid 200 301 10m;   # 200 dan 301 → cache 10 menit
        proxy_cache_valid 404           1m;    # 404 → cache 1 menit
        proxy_cache_valid any           1m;    # Status lain → cache 1 menit

        # Tambahkan header untuk debugging: HIT/MISS/BYPASS/EXPIRED
        add_header X-Cache-Status $upstream_cache_status;

        proxy_pass http://backend;
    }
}

Cache Bypass: Kapan Tidak Pakai Cache #

Tidak semua request boleh di-cache. Request yang terautentikasi atau yang melakukan perubahan data harus selalu ke backend:

location /api/ {
    proxy_cache app_cache;

    # Bypass cache jika ada cookie session atau header Authorization
    proxy_cache_bypass $cookie_session_id $http_authorization;
    proxy_no_cache     $cookie_session_id $http_authorization;

    # Bypass berdasarkan method
    set $bypass_cache 0;
    if ($request_method != GET) {
        set $bypass_cache 1;
    }
    if ($request_method != HEAD) {
        set $bypass_cache 1;
    }
    proxy_cache_bypass $bypass_cache;
    proxy_no_cache     $bypass_cache;

    proxy_cache_key "$request_method$host$request_uri";
    proxy_cache_valid 200 5m;

    proxy_pass http://backend;
}

Aturan praktis: hanya cache request GET dan HEAD untuk endpoint yang tidak memerlukan autentikasi.


Stale Cache: Sajikan Cache Lama saat Backend Down #

Salah satu fitur paling berguna dari proxy cache — jika backend error atau lambat, Nginx bisa menyajikan versi cache yang sudah expired daripada menampilkan error 502:

location /api/ {
    proxy_cache app_cache;
    proxy_cache_valid 200 5m;

    # Sajikan cache lama jika backend error atau sedang diupdate
    proxy_cache_use_stale error timeout updating
                          http_500 http_502 http_503 http_504;

    # Berapa lama stale cache boleh digunakan
    proxy_cache_revalidate on;

    # Hanya satu request yang diteruskan ke backend untuk mengupdate cache
    # sementara yang lain mendapat stale cache
    proxy_cache_lock on;
    proxy_cache_lock_timeout 5s;

    proxy_pass http://backend;
}

proxy_cache_lock sangat penting untuk mencegah “thundering herd” — situasi di mana cache expired dan ratusan request sekaligus diteruskan ke backend. Dengan lock, hanya satu request yang diteruskan, sisanya menunggu sambil mendapat stale cache.


Memantau Efektivitas Cache #

Header X-Cache-Status yang ditambahkan di konfigurasi memberitahu status cache untuk setiap response:

HIT     → response dari cache, backend tidak disentuh
MISS    → request baru, response dari backend, disimpan ke cache
BYPASS  → request melewati cache (kondisi bypass terpenuhi)
EXPIRED → cache ada tapi sudah expired, request diteruskan ke backend
STALE   → cache expired tapi backend error, sajikan cache lama
UPDATING → cache sedang diupdate oleh request lain (cache lock)
# Monitor cache hit rate dari log
grep 'X-Cache-Status' /var/log/nginx/access.log | \
    awk '{print $NF}' | sort | uniq -c | sort -rn

# Lihat ukuran cache di disk
du -sh /var/cache/nginx/

Cache hit rate yang baik biasanya di atas 80%. Jika hit rate rendah, evaluasi apakah proxy_cache_key terlalu spesifik atau masa cache terlalu pendek.


Ringkasan #

  • Cache header (expires, Cache-Control) untuk aset statis adalah cara paling efektif — browser tidak perlu ke server sama sekali.
  • Gunakan header immutable hanya untuk file dengan hash di nama file — file yang tidak akan pernah berubah.
  • proxy_cache_lock on mencegah thundering herd saat cache expired — hanya satu request ke backend, sisanya tunggu.
  • proxy_cache_use_stale meningkatkan keandalan — sajikan cache lama daripada error 502 saat backend bermasalah.
  • Pantau cache hit rate melalui header X-Cache-Status — target hit rate > 80% untuk endpoint yang bisa di-cache.

← Sebelumnya: Kompresi Gzip   Berikutnya: Keepalive →

About | Author | Content Scope | Editorial Policy | Privacy Policy | Disclaimer | Contact