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
immutablehanya untuk file dengan hash di nama file — file yang tidak akan pernah berubah.proxy_cache_lock onmencegah thundering herd saat cache expired — hanya satu request ke backend, sisanya tunggu.proxy_cache_use_stalemeningkatkan 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.